Lightweight and extensible compatibility layer between dataframe libraries!
Extremely lightweight and extensible compatibility layer between dataframe libraries!
Seamlessly support all, without depending on any!
Get started!
pip install narwhals
conda install -c conda-forge narwhals
There are three steps to writing dataframe-agnostic code using Narwhals:
use narwhals.from_native
to wrap a pandas/Polars/Modin/cuDF/PyArrow
DataFrame/LazyFrame in a Narwhals class
use narwhals.to_native
to return an object to the user in its original
dataframe flavour. For example:
Narwhals allows you to define dataframe-agnostic functions. For example:
import narwhals as nw
from narwhals.typing import IntoFrameT
def agnostic_function(
df_native: IntoFrameT,
date_column: str,
price_column: str,
) -> IntoFrameT:
return (
nw.from_native(df_native)
.group_by(nw.col(date_column).dt.truncate("1mo"))
.agg(nw.col(price_column).mean())
.sort(date_column)
.to_native()
)
You can then pass pandas.DataFrame
, polars.DataFrame
, polars.LazyFrame
, duckdb.DuckDBPyRelation
,
pyspark.sql.DataFrame
, pyarrow.Table
, and more, to agnostic_function
. In each case, no additional
dependencies will be required, and computation will stay native to the input library:
import pandas as pd
import polars as pl
from datetime import datetime
data = {
"date": [datetime(2020, 1, 1), datetime(2020, 1, 8), datetime(2020, 2, 3)],
"price": [1, 4, 3],
}
print("pandas result:")
print(agnostic_function(pd.DataFrame(data), "date", "price"))
print()
print("Polars result:")
print(agnostic_function(pl.DataFrame(data), "date", "price"))
pandas result:
date price
0 2020-01-01 2.5
1 2020-02-01 3.0
Polars result:
shape: (2, 2)
┌─────────────────────┬───────┐
│ date ┆ price │
│ --- ┆ --- │
│ datetime[μs] ┆ f64 │
╞═════════════════════╪═══════╡
│ 2020-01-01 00:00:00 ┆ 2.5 │
│ 2020-02-01 00:00:00 ┆ 3.0 │
└─────────────────────┴───────┘
See the tutorial for several examples!
If you said yes to both, we’d love to hear from you!
See roadmap discussion on GitHub
for an up-to-date plan of future work.
Join the party!
Feel free to add your project to the list if it’s missing, and/or
chat with us on Discord if you’d like any support.
Narwhals is 100% independent, community-driven, and community-owned.
We are extremely grateful to the following organisations for having
provided some funding / development time:
If you contribute to Narwhals on your organization’s time, please let us know. We’d be happy to add your employer
to this list!
Narwhals has been featured in several talks, podcasts, and blog posts:
Talk Python to me Podcast
Ahoy, Narwhals are bridging the data science APIs
Python Bytes Podcast
Episode 402, topic #2
Super Data Science: ML & AI Podcast
Narwhals: For Pandas-to-Polars DataFrame Compatibility
Sample Space Podcast | probabl
How Narwhals has many end users … that never use it directly. - Marco Gorelli
The Real Python Podcast
Narwhals: Expanding DataFrame Compatibility Between Libraries
Pycon Lithuania
Marco Gorelli - DataFrame interoperatiblity - what’s been achieved, and what comes next?
Pycon Italy
How you can write a dataframe-agnostic library - Marco Gorelli
Polars Blog Post
Polars has a new lightweight plotting backend
Quansight Labs blog post (w/ Scikit-Lego)
How Narwhals and scikit-lego came together to achieve dataframe-agnosticism
Thanks to Olha Urdeichuk for the illustration!