This release has been yanked by its maintainers, and will be ignored by installers, except when explicitly specified.
Consider using release 0.1.5 instead.
narwhals-datafusion
Apache DataFusion backend for
Narwhals, registered through the
narwhals.plugins entry point.
pip install narwhals-datafusion # core
pip install "narwhals-datafusion[extra-functions]" # + mode, skew, kurtosis
Usage
import narwhals as nw
import pyarrow as pa
from datafusion import SessionContext
ctx = SessionContext()
df = ctx.from_arrow(pa.table({"a": [1, 2, 3], "b": ["x", "y", "x"]}))
lf = nw.from_native(df) # nw.LazyFrame on this backend
result = (
lf.group_by("b")
.agg(nw.col("a").sum())
.sort("b")
.collect(backend="pyarrow")
)
Everything is lazy until .collect(): expressions become datafusion.Expr,
frame verbs become datafusion.DataFrame methods, and DataFusion executes the
plan. Dtypes are pyarrow end-to-end.
Architecture
A subclass of narwhals' SQL layer (narwhals._sql, narwhals._compliant),
the layer DuckDB, Ibis and Spark also use. Tested against the narwhals release
vendored as the narwhals/ submodule (2.25) and datafusion 54, the major
pyproject.toml pins.
| Module | Class |
|---|---|
dataframe.py |
DataFusionLazyFrame: frame verbs over datafusion.DataFrame |
expr.py |
DataFusionExpr: the SQLExpr hooks, aggregates, windows, casts |
namespace.py |
DataFusionNamespace: SQLNamespace primitives, IO, horizontal functions |
group_by.py, selectors.py, expr_str/dt/list/struct.py |
supporting surface |
utils.py |
function-name remapping, window/sort builders, dtype bridge via narwhals._arrow |
mode, skew, kurtosis
These aggregates live in the Rust-only
datafusion-extra-functions
crate. The extra-functions extra installs
datafusion-extra-functions-ffi,
a prebuilt wheel exposing them through datafusion-python's
__datafusion_aggregate_udf__ capsule protocol. Without it the three methods
raise NotImplementedError. The wheel pins the datafusion major it was built
for.
API coverage
narwhals 2.25 on datafusion 54. ⚠️ entries work with the caveat in parentheses; see Known limitations.
| Namespace | ✅ Supported | ⚠️ Partial | ❌ Not supported |
|---|---|---|---|
Expr |
abs alias all any any_value ceil clip cos count cum_count cum_max cum_min cum_sum diff exp fill_nan first floor is_between is_close is_duplicated is_finite is_first_distinct is_in is_last_distinct is_nan is_null is_unique last len log max mean median min null_count over pipe rank rolling_mean rolling_std rolling_sum rolling_var round shift sin sqrt std sum var |
cast (no Enum) · fill_null (no strategy + limit) · kurtosis ([extra-functions] extra) · mode ([extra-functions] extra, keep="any" only) · n_unique (not over windows) · replace_strict (explicit default required) · skew ([extra-functions] extra) |
cum_prod quantile |
Expr.str |
contains ends_with head len_chars pad_end pad_start replace_all slice split starts_with strip_chars strip_chars_end strip_chars_start tail to_lowercase to_time to_uppercase zfill |
to_date/to_datetime (explicit format required) · to_titlecase (no word breaks on digits) |
replace (use replace_all) |
Expr.dt |
convert_time_zone date day hour microsecond millisecond minute month nanosecond ordinal_day second to_string truncate weekday year |
replace_time_zone (None/"UTC" only) |
offset_by timestamp total_microseconds total_milliseconds total_minutes total_nanoseconds total_seconds |
Expr.list |
contains get len max min sort |
unique (maintain_order=False only) |
mean median sum |
Expr.struct |
field |
||
LazyFrame |
collect collect_schema drop drop_nulls filter group_by head join rename select sort top_k unique unpivot with_columns with_row_index |
explode (single column) · sink_parquet (file path only) |
join_asof |
Not listed: methods narwhals does not support on any lazy backend
(Expr.filter, Expr.drop_nulls, Expr.unique, Expr.map_batches,
Expr.ewm_mean, LazyFrame.tail, LazyFrame.gather_every).
Known limitations (as of datafusion 54)
join_asof, exactquantile,cum_prod,list.sum/mean/median,dt.total_*,dt.offset_by,dt.timestamp,str.replace,Enumcasts: no engine support, raiseNotImplementedError.mode,skew,kurtosis: need theextra-functionsextra.n_unique().over(...)raises: DataFusion ignoresDISTINCTinside window aggregates, which would return wrong results. It also dropsORDER BYandIGNORE NULLSthere; this backend moves those onto the window itself.fill_null(strategy=..., limit=n)raises: bounded frames withfirst_value/last_valueneedretract_batch, not implemented engine-side.replace_time_zonesupportsNoneand"UTC"only; useconvert_time_zonefor instant-preserving conversions.str.to_datetime/to_daterequire an explicitformat.replace_strictrequires an explicitdefault.nw.scan_csv/nw.scan_parquetcannot dispatch to a plugin backend yet (narwhals gap); read with aSessionContextand pass the frame tonw.from_native.str.to_titlecaseusesinitcap, which does not break words on digits.- Row order is guaranteed only after
sort:concatmay interleave inputs and backwardfill_nullmay reorder rows.
Development
git submodule update --init # narwhals at the tested tag
uv sync --group tests --extra extra-functions
uv run --group tests pytest tests # this package's tests
uv run --group tests python run_tests.py # narwhals' suite, known failures deselected
See CONTRIBUTING.md.
Release files for narwhals-datafusion 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| narwhals_datafusion-0.1.3.tar.gz | 21.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| narwhals_datafusion-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 48.2 kB
Release files / narwhals_datafusion-0.1.3.tar.gz
| Download URL | narwhals_datafusion-0.1.3.tar.gz |
|---|---|
| Size | 21.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d780bca638fb5d53504eb88c43925549982496e71edf1d83be2ea5ac606b66ec
|
|
BLAKE2b-256 checksum How to use checksums |
356f3958a7d2b1945414a8b483bc00573c583e0ea34bc3f590ff924ad6450a39
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency logRelease files / narwhals_datafusion-0.1.3-py3-none-any.whl
| Download URL | narwhals_datafusion-0.1.3-py3-none-any.whl |
|---|---|
| Size | 27.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2407c07298958dd05f78ca97d93f24381413f839438cdd0c6d7526bb38025ef2
|
|
BLAKE2b-256 checksum How to use checksums |
7c1611c8850ecf38b63109f8a15728abb5ed8b01bcc3aef5a2a4ec7e01ed4707
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency log