Ibis
FrameworkFreePortable Python dataframe API across 20+ backends.
Capabilities16 decomposed
lazy expression construction with symbolic dataframe operations
Medium confidenceBuilds an abstract syntax tree (AST) of dataframe operations without executing them, using Ibis's core expression system (ibis/expr/operations and ibis/expr/types) to represent table selections, projections, filters, and aggregations as composable symbolic objects. Expressions are constructed through method chaining on Table and Column types, with each operation creating a new immutable expression node that references its inputs, enabling deferred execution and optimization before compilation to backend-specific code.
Uses a strongly-typed expression system with deferred execution via immutable AST nodes (ibis/expr/operations/core.py) rather than eager evaluation like pandas, enabling backend-agnostic query representation and multi-pass optimization before compilation. The expression graph is traversed and validated at construction time using pattern matching (ibis/common/patterns.py) to catch type errors early.
Unlike pandas (eager evaluation) or SQLAlchemy (SQL-first), Ibis provides a Python-native lazy API with full type safety and backend portability, allowing the same code to run on DuckDB for 1GB datasets and BigQuery for 1TB datasets without modification.
multi-backend sql compilation with sqlglot integration
Medium confidenceTranslates Ibis expression trees into backend-specific SQL dialects using SQLGlot as the compilation engine (ibis/backends/sql/compiler.py integration). Each backend registers its own SQL compiler that walks the expression DAG, applies backend-specific type mappings (via ibis/expr/operations type registry), and generates optimized SQL strings. The compilation layer handles dialect differences (e.g., window function syntax, string functions, date arithmetic) transparently, allowing a single Ibis expression to produce valid SQL for DuckDB, PostgreSQL, BigQuery, Snowflake, Spark SQL, and 15+ other engines.
Delegates SQL generation to SQLGlot rather than implementing dialect handling directly, enabling support for 20+ backends without maintaining separate code paths. Each backend registers a custom compiler class (e.g., DuckDBCompiler, BigQueryCompiler) that inherits from a base SQL compiler and overrides dialect-specific methods, creating a plugin architecture for new backends.
More comprehensive dialect support than hand-rolled SQL generation (e.g., in Polars or Dask), and more portable than SQLAlchemy which requires explicit dialect specification and doesn't provide a unified dataframe API across backends.
expression optimization and rewriting via e-graph
Medium confidenceApplies automated query optimization using an e-graph (equality graph) data structure (ibis/common/egraph.py) that represents equivalent expressions and enables rewriting rules to find more efficient query plans. The optimizer applies algebraic transformations (e.g., pushing filters down before joins, eliminating redundant projections, constant folding) to the expression DAG before compilation. Rewriting rules are defined declaratively and applied iteratively until a fixed point is reached, with cost-based selection to choose the most efficient equivalent expression.
Uses an e-graph (equality graph) data structure to represent multiple equivalent expressions and apply rewriting rules systematically, rather than ad-hoc pattern matching. This enables discovering optimization opportunities that require multiple rewriting steps and provides a principled way to add new optimization rules without affecting existing ones. The e-graph approach is inspired by egg (Equality Saturation) and enables exhaustive search for optimal query plans.
More principled than hand-coded optimization rules (e.g., in Pandas or Polars) and more comprehensive than backend-specific optimizers (which only see the final SQL). Comparable to Calcite's cost-based optimizer but with a simpler, more maintainable implementation.
comprehensive backend test suite with docker environment
Medium confidenceProvides a unified testing framework (ibis/backends/tests/) that runs the same test suite against all 20+ backends using Docker containers for database services. Tests are organized by feature (SQL, aggregation, window functions, etc.) and automatically skipped for backends that don't support a feature. The test infrastructure includes base test classes (e.g., BackendTestBase) that define test methods, and backend-specific test classes that override methods for backend-specific behavior. Docker Compose is used to spin up database services (PostgreSQL, MySQL, BigQuery emulator, etc.) for testing.
Implements a shared test suite (ibis/backends/tests/) that runs against all backends, with automatic skipping for unsupported features via decorators (e.g., @pytest.mark.notimplemented). This ensures consistent behavior across backends and makes it easy to add new backends by inheriting from base test classes. Docker Compose is used to manage database services, enabling reproducible testing across different environments.
More comprehensive than backend-specific tests (which only test one backend) and more maintainable than duplicating tests for each backend. Comparable to Polars' test infrastructure but with support for 20+ backends instead of just one.
streaming and incremental data loading from multiple sources
Medium confidenceSupports loading data incrementally from files (Parquet, CSV, JSON), databases (via SQL), and cloud storage (S3, GCS, Azure Blob) using backend-specific readers that stream data without loading it all into memory. Ibis abstracts the loading logic behind a unified API (ibis.read_parquet(), ibis.read_csv(), ibis.read_sql()) that returns a Table expression. For backends that support it (e.g., DuckDB), data is read lazily and only materialized when .execute() is called. For backends that don't support lazy reading, data is materialized locally and pushed to the backend.
Provides a unified API for loading data from multiple sources (files, databases, cloud storage) that abstracts backend-specific reader implementations. For backends that support lazy reading (e.g., DuckDB), data is read lazily and only materialized when needed. For backends that don't, data is materialized locally and pushed to the backend, enabling a consistent API across all backends.
More unified than using backend-specific readers directly (e.g., google.cloud.bigquery.load_table_from_uri) and more flexible than Pandas (which loads all data into memory). Comparable to Polars but with multi-backend support and better cloud storage integration.
deferred computation with expression caching and reuse
Medium confidenceCaches expression objects to enable efficient reuse of intermediate results without recomputation. When the same expression is used multiple times in a query (e.g., a filtered table used in two different aggregations), Ibis detects the duplication and generates SQL that computes the expression once and reuses it (via CTEs or subqueries). The caching system uses expression hashing and structural equality to detect duplicates, and is transparent to the user — no explicit caching API is required.
Automatically detects repeated subexpressions in the expression DAG using structural hashing and generates SQL with CTEs or subqueries to avoid recomputation. This is done transparently without requiring explicit caching API calls, making it easy for users to benefit from caching without changing their code.
More automatic than explicit caching (e.g., in Spark) and more efficient than recomputing the same expression multiple times. Unique among dataframe libraries in providing transparent expression caching.
string operations and text manipulation with backend-specific functions
Medium confidenceImplements string operations (substring, length, upper, lower, replace, split, concatenate, regex matching) that compile to backend-specific string function syntax. The system abstracts over differences in string function names and behavior across backends (e.g., SUBSTR vs SUBSTRING, regex syntax differences), providing a unified API for text manipulation.
Abstracts string function syntax across backends by providing a unified API (e.g., t.column.upper(), t.column.substr(0, 5)) that compiles to backend-specific functions. The system handles backends with limited string function support by providing fallback implementations.
More portable than raw SQL string functions because the same code works across backends; more readable than Pandas string methods because it integrates with the fluent API.
array and struct operations with nested data type support
Medium confidenceSupports operations on complex types (arrays, structs) including element access, flattening, unnesting, and aggregation of nested data. The system compiles array/struct operations to backend-specific syntax (UNNEST in SQL, explode in Spark, LATERAL FLATTEN in Snowflake), handling differences in nested data support across backends.
Provides a unified API for nested data operations across backends with vastly different nested type support, using backend-specific compilation (UNNEST, explode, LATERAL FLATTEN) to handle differences. The system includes type inference for nested structures.
More portable than raw SQL nested operations because the same code works across backends; more flexible than Pandas (which lacks native nested type support) because it works with modern data warehouses' native nested types.
backend-agnostic connection and execution abstraction
Medium confidenceProvides a unified connection interface (ibis.backends.Backend base class) that abstracts away backend-specific connection logic, authentication, and execution details. Developers call ibis.duckdb.connect(), ibis.bigquery.connect(), or ibis.snowflake.connect() with backend-specific credentials, which returns a Backend instance with a standard API (.sql(), .execute(), .to_pandas()). The Backend class handles query compilation, parameter binding, result fetching, and type conversion, allowing code to switch backends by changing a single line (e.g., from DuckDB to BigQuery) without modifying query logic.
Implements a plugin architecture where each backend (DuckDB, BigQuery, Snowflake, etc.) is a separate module (ibis/backends/duckdb/, ibis/backends/bigquery/) with its own Backend subclass, compiler, and type mapper. This allows new backends to be added without modifying core Ibis code, and enables backends to be installed optionally (e.g., pip install ibis-bigquery).
More unified than using backend-specific clients directly (google-cloud-bigquery, pyspark), and more flexible than Polars which is single-backend (DuckDB-based) or Pandas which doesn't support distributed execution.
type-safe schema inference and validation
Medium confidenceAutomatically infers and validates data types for all expressions using Ibis's type system (ibis/expr/types/core.py, ibis/common/typing.py). When a table is created (via .sql(), .memtable(), or backend connection), Ibis introspects the schema and maps backend-specific types (e.g., BigQuery's BIGNUMERIC) to Ibis types (int64, float64, string, timestamp, etc.). All operations (filter, select, join, aggregate) validate that operands have compatible types at expression construction time, catching type errors before execution. Type coercion rules are applied automatically (e.g., int + float → float) and can be customized per backend.
Uses a declarative type system with explicit type objects (ibis.int64, ibis.string, etc.) rather than Python's built-in types, enabling precise representation of database types (e.g., decimal precision, timestamp timezone). Type validation is performed at expression construction time using pattern matching (ibis/common/patterns.py) and a rules engine (ibis/expr/rules.py), catching errors before compilation.
More rigorous than pandas (which infers types at runtime and allows implicit coercion) and more flexible than SQLAlchemy (which requires explicit type declarations). Provides early error detection comparable to statically-typed languages while maintaining Python's dynamic feel.
composable table operations with method chaining
Medium confidenceProvides a fluent API for building complex queries through method chaining on Table objects, where each method (select, filter, join, group_by, order_by, limit) returns a new Table expression. Operations are composable and can be chained arbitrarily (e.g., t.filter(...).select(...).join(...).group_by(...).aggregate(...)), with each step creating a new expression node in the DAG. The API mirrors SQL semantics but uses Python idioms (e.g., filter instead of WHERE, select instead of SELECT), making it accessible to Python developers unfamiliar with SQL.
Implements method chaining through immutable expression objects where each method returns a new Table with the operation appended to the expression DAG, rather than mutating state. This enables safe composition and allows intermediate results to be reused without side effects. The API is designed to mirror SQL semantics (select, filter, join, group_by) while using Python conventions (snake_case, keyword arguments).
More Pythonic than raw SQL strings and more flexible than pandas method chaining (which is eager and single-backend). Comparable to Polars API but with multi-backend support and lazy evaluation across all backends.
cross-backend join and set operations with type alignment
Medium confidenceEnables joining tables from different backends (e.g., DuckDB table joined with BigQuery table) by materializing one side locally and performing the join in the target backend, with automatic type alignment and schema reconciliation. Implements set operations (union, intersection, difference) across heterogeneous backends by converting schemas to a common type representation and handling NULL semantics correctly. The join logic (ibis/expr/operations/relations.py) validates that join keys have compatible types and generates backend-specific join SQL with proper type casting.
Automatically handles type mapping and schema reconciliation across backends by materializing one table locally (using .to_pandas() or backend-specific export) and then performing the join in the target backend with explicit type casting. This avoids requiring a common execution engine and works with any combination of backends, though at the cost of materialization overhead.
Unique among dataframe libraries in supporting cross-backend joins without a shared execution engine. More practical than Spark (which requires all data in Spark) or Pandas (which is single-machine only), though slower than native joins within a single backend.
aggregation and grouping with window functions
Medium confidenceProvides aggregation operations (sum, mean, count, min, max, etc.) and window functions (row_number, rank, lag, lead, etc.) that compile to backend-specific SQL. Aggregations are applied via .aggregate() or .group_by() methods, which generate GROUP BY clauses with proper type handling for aggregate functions. Window functions are constructed via .over() method, specifying partition and order clauses, and compile to OVER (PARTITION BY ... ORDER BY ...) syntax. The implementation handles edge cases like NULL aggregation, empty groups, and frame specifications (ROWS BETWEEN ... AND ...) correctly across backends.
Implements window functions through a fluent API (.over(partition_by=..., order_by=...)) that generates backend-specific window function SQL, with automatic type inference for aggregate results. The aggregation system uses a separate aggregation expression type (Aggregate) that tracks which columns are grouped vs aggregated, enabling proper type validation and SQL generation.
More comprehensive window function support than Pandas (which has limited window function API) and more portable than raw SQL (which requires backend-specific syntax). Comparable to Polars but with multi-backend support.
sql fragment embedding and mixed-mode queries
Medium confidenceAllows embedding raw SQL strings directly into Ibis expressions via ibis.sql() function, enabling developers to use backend-specific SQL features (e.g., BigQuery ML, Snowflake stored procedures) that aren't exposed through the Ibis API. SQL fragments are parsed and type-annotated, then composed with other Ibis operations in the expression DAG. The system validates that SQL fragments produce tables/columns with compatible schemas and types, and compiles them into the final backend-specific query without modification.
Provides an escape hatch for backend-specific features by allowing raw SQL strings to be embedded as first-class expressions in the Ibis DAG, with optional type annotation and schema validation. SQL fragments are treated as opaque operations that produce tables/columns with specified schemas, enabling composition with other Ibis operations without requiring the SQL to be parsed or understood by Ibis.
More flexible than pure Ibis (which doesn't support backend-specific features) and more type-safe than raw SQL (which has no schema validation). Unique among dataframe libraries in supporting this level of SQL embedding while maintaining expression composability.
lazy result materialization with multiple output formats
Medium confidenceDefers execution until explicitly requested via .execute(), .to_pandas(), .to_pyarrow(), or .to_csv() methods, allowing developers to build complex queries without triggering computation. When materialization is requested, the expression DAG is compiled to backend-specific SQL, executed on the backend, and results are fetched and converted to the requested format (Pandas DataFrame, PyArrow Table, CSV file, etc.). The system handles result streaming for large datasets, type conversion between backend types and Python types, and NULL value representation correctly.
Implements lazy evaluation by deferring all computation until .execute() or similar methods are called, at which point the expression DAG is compiled and executed. Multiple output formats are supported through pluggable converters (Pandas, PyArrow, CSV) that handle type mapping and NULL representation, allowing the same query to be materialized in different formats without recompilation.
More flexible than Pandas (eager evaluation, single format) and more efficient than materializing to Pandas then converting (which requires two passes). Comparable to Polars lazy API but with multi-backend support and more output format options.
backend-specific type mapping and operation registry
Medium confidenceMaintains a registry of backend-specific type mappings (e.g., BigQuery NUMERIC → Ibis decimal128) and operation implementations (e.g., string functions, date arithmetic) that vary across backends. Each backend registers its type mapper (ibis/backends/*/datatypes.py) and operation compiler (ibis/backends/*/compiler.py) that define how Ibis types and operations map to backend-specific SQL. When an operation is not supported by a backend, the registry falls back to Python evaluation or raises NotImplementedError, allowing graceful degradation or explicit error messages.
Implements a plugin architecture where each backend registers its type mapper and operation compiler as separate classes (e.g., BigQueryTypeMapper, BigQueryCompiler) that inherit from base classes and override backend-specific methods. This allows new backends to be added without modifying core Ibis code, and enables backends to be installed as optional dependencies (e.g., pip install ibis-bigquery).
More extensible than hand-coded type mapping (e.g., in Polars) and more maintainable than a monolithic type registry. Comparable to SQLAlchemy's type system but with better support for modern data warehouse types (e.g., nested structures, geospatial types).
Capabilities are decomposed by AI analysis. Each maps to specific user intents and improves with match feedback.
Related Artifactssharing capabilities
Artifacts that share capabilities with Ibis, ranked by overlap. Discovered automatically through the match graph.
Polars
Rust-powered DataFrame library 10-100x faster than pandas.
polars
Blazingly fast DataFrame library
mcp-sql-optimizer
A powerful Model Context Protocol (MCP) server that analyzes, optimizes, and suggests indexes for SQL queries across multiple dialects (PostgreSQL, MySQL, Oracle, SQL Server). Built with Python and `sqlglot`.
Sdf
SDF is a next-generation build system for data...
vaex
Out-of-Core DataFrames to visualize and explore big tabular datasets
databend
Data Agent Ready Warehouse : One for Analytics, Search, AI, Python Sandbox. — rebuilt from scratch. Unified architecture on your S3.
Best For
- ✓Data engineers building ETL pipelines who need query optimization
- ✓ML practitioners preparing datasets locally before scaling to cloud warehouses
- ✓Teams migrating from pandas to distributed backends without rewriting code
- ✓Teams using multiple data warehouses (BigQuery + Snowflake + Spark) who need code reuse
- ✓Data engineers who need to debug generated SQL and understand backend-specific behavior
- ✓Organizations migrating between warehouse vendors without rewriting pipelines
- ✓Data engineers building complex queries that benefit from algebraic optimization
- ✓Teams with performance-critical pipelines where query optimization matters
Known Limitations
- ⚠Expressions are unbound until connected to a backend — cannot execute without calling .execute() or .to_pandas()
- ⚠No automatic query optimization across all backends — optimization rules vary by backend implementation
- ⚠Circular references in expression graphs are not supported; DAG structure is enforced
- ⚠Some advanced Ibis operations may not be supported on all backends — falls back to Python evaluation or raises NotImplementedError
- ⚠SQL compilation adds ~50-200ms overhead per query depending on expression complexity
- ⚠Backend-specific SQL functions (e.g., BigQuery ML functions) require explicit Ibis operation definitions
Requirements
Input / Output
UnfragileRank
UnfragileRank is computed from adoption signals, documentation quality, ecosystem connectivity, match graph feedback, and freshness. No artifact can pay for a higher rank.
About
Portable Python dataframe library that provides a unified API across 20+ execution backends including DuckDB, Spark, BigQuery, and Snowflake. Write once, run anywhere — same code works locally and at warehouse scale for ML data prep.
Categories
Alternatives to Ibis
Are you the builder of Ibis?
Claim this artifact to get a verified badge, access match analytics, see which intents users search for, and manage your listing.
Get the weekly brief
New tools, rising stars, and what's actually worth your time. No spam.
Data Sources
Looking for something else?
Search →