Extremely lightweight and extensible compatibility layer between dataframe libraries!
Seamlessly support all, without depending on any!
Get started!
Table of contentsconda 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.
Sponsors and institutional partnersNarwhals 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!
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4