Skip to content

DataFrame Backends

xbbg is DataFrame-library agnostic. The core engine returns Apache Arrow data; conversion to your preferred library happens at the boundary before results are returned to you. This means you can use whichever DataFrame library fits your stack without forking or wrapping xbbg.

The backend abstraction is provided by narwhals, which handles the translation layer between Arrow and the supported libraries.

Eager backends return a fully materialized DataFrame immediately.

BackendOutput typeBest for
pandaspd.DataFrameTraditional workflows, ecosystem compatibility
polarspl.DataFrameHigh performance, large datasets
pyarrowpa.TableZero-copy interop, memory efficiency
narwhalsNarwhals DataFrameLibrary-agnostic code
modinModin DataFramePandas API with parallel execution
cudfcuDF DataFrameGPU-accelerated processing (requires NVIDIA)

Lazy backends defer execution. The query graph is built when you call xbbg functions and evaluated only when you explicitly trigger execution (e.g. .collect() for Polars, .execute() for DuckDB).

BackendOutput typeBest for
polars_lazypl.LazyFrameDeferred execution, query optimization
narwhals_lazyNarwhals LazyFrameLibrary-agnostic lazy evaluation
duckdbDuckDB relationSQL analytics, OLAP queries
daskDask DataFrameOut-of-core and distributed computing
ibisIbis TableUnified interface to many backends
pysparkSpark DataFrameBig data processing (requires Java)
sqlframeSQLFrame DataFrameSQL-first DataFrame operations

Set the backend once for your session. All subsequent calls use it unless overridden.

import xbbg
from xbbg import Backend
xbbg.set_backend(Backend.POLARS)
# All calls now return pl.DataFrame
from xbbg import blp
df = blp.bdp('AAPL US Equity', 'PX_LAST')

You can also pass a string:

xbbg.set_backend('polars')

Pass backend as a keyword argument to any data function. This overrides the global default for that call only.

from xbbg import blp
# Overrides the global default for this call
df = blp.bdp('AAPL US Equity', 'PX_LAST', backend='pandas')

Not all backends are installed in every environment. Use these utilities to inspect what is available before writing code that assumes a specific backend.

from xbbg import get_available_backends, is_backend_available, print_backend_status
# Returns a list of installed backend names
print(get_available_backends())
# ['pandas', 'polars', 'pyarrow', ...]
# Check a specific backend
if is_backend_available('polars'):
print("Polars is installed")
# Print a detailed status table for all backends
print_backend_status()
from xbbg import blp, Backend
df = blp.bdp('AAPL US Equity', 'PX_LAST', backend=Backend.PANDAS)
# Returns pd.DataFrame
print(type(df)) # <class 'pandas.core.frame.DataFrame'>

PyArrow is the zero-copy option. Because xbbg’s internal representation is Arrow, returning a pa.Table requires no serialization or memory copy. Use this when passing data to other Arrow-compatible systems (DuckDB, Polars, Spark via Arrow flight, etc.) or when memory pressure matters.

Polars is the best choice for pure computation on large datasets. Its columnar engine and lazy execution model handle datasets that would be slow or impractical in pandas. The polars_lazy backend lets you chain additional query steps before triggering evaluation.

pandas remains the widest-compatibility option. Use it when integrating with libraries that only accept pd.DataFrame, or when working with existing pandas-based pipelines. It is not required as a dependency — if your code uses the polars or pyarrow backends exclusively, pandas does not need to be installed.

Lazy backends (DuckDB, Polars lazy, Dask, etc.) are useful when you want to compose queries across multiple xbbg calls before materializing any data, or when the result set is too large to hold in memory.

  • Output Formats — control the shape of returned data (LONG, LONG_TYPED, etc.)
  • API Reference — full function documentation with all parameters