A pandas-like API wrapper around Polars for high-performance data manipulation
Project description
A high-performance pandas-like DataFrame library powered by Polars
Combine the familiar pandas API with Polars' blazing-fast performance
โจ Features
- ๐ผ Pandas-like API โ Use familiar pandas syntax without learning a new library
- โก Polars Backend โ Leverage Polars' optimized Rust engine for maximum performance
- ๐ Comprehensive I/O โ Read/write CSV, Parquet, JSON, and Excel files
- ๐ฏ Automatic Fallback โ Seamless fallback to pandas for unimplemented methods
- ๐ฌ Built-in Profiler โ Line-by-line comparison of your pandas code vs nitro-pandas with
profile_compare - ๐ง Type Safety โ Support for pandas-like type casting and schema inference
๐ฏ Why nitro-pandas?
nitro-pandas bridges the gap between pandas' user-friendly API and Polars' exceptional performance. Replace import pandas as pd with import nitro_pandas as npd and get faster code without changing anything else.
Performance Comparison
Benchmarked on the Books Rating dataset (~3M rows, 10 columns) using npd.profile_compare. All times are averaged wall-clock seconds.
| Operation | pandas | nitro-pandas | Speedup |
|---|---|---|---|
| Read CSV | 13.04s | 1.09s | 12.0x โ |
| Rename columns | 0.11s | 0.001s | 80x โ |
| Drop duplicates | 0.52s | 0.42s | 1.2x โ |
Filter (df[df["Price"] > 0]) |
0.028s | 0.009s | 3.1x โ |
| Chained filters | 0.008โ0.014s | 0.001โ0.002s | 5โ8x โ |
| GroupBy + mean | 0.030s | 0.004s | 7.5x โ |
| GroupBy + count | 0.032s | 0.004s | 8.9x โ |
| nlargest (top-N) | 0.027โ0.029s | 0.007โ0.009s | 3โ4x โ |
String filter (str.contains) |
0.15โ0.20s | 0.02โ0.03s | 5โ9x โ |
| pivot_table | 0.008s | 0.003s | 2.8x โ |
| sample (50k rows) | 0.010s | 0.001s | 8.0x โ |
| describe | 0.012s | 0.003s | 4.2x โ |
| sort_values | 0.041s | 0.018s | 2.3x โ |
| TOTAL pipeline | 14.47s | 1.68s | 8.6x โ |
Summary: 8.6x overall speedup on a realistic 13-step production pipeline. The biggest gains are on I/O, string operations, groupby, and sampling โ the operations that dominate real-world workloads.
Results may vary based on data size and hardware.
๐ฆ Installation
# Using uv (recommended)
uv add nitro-pandas
# Using pip
pip install nitro-pandas
Requirements
- Python 3.11+
- Dependencies (automatically installed):
polars>=1.30.0โ High-performance DataFrame enginepandas>=2.2.3โ For fallback methodsline-profiler>=5.0.2โ Forprofile_comparefastexcel>=0.7.0โ Fast Excel readingopenpyxl>=3.1.5โ Excel file supportpyarrow>=20.0.0โ Parquet file support
๐ Quick Start
Basic Usage
import nitro_pandas as npd
# Create a DataFrame (pandas-like syntax)
df = npd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['Paris', 'London', 'New York']
})
# Filter data
filtered = df[df['age'] > 30]
# GroupBy
result = df.groupby('city')['age'].mean()
Reading Files
# Read CSV
df = npd.read_csv('data.csv')
# Read with lazy evaluation (optimized for large files)
lf = npd.read_csv_lazy('large_data.csv')
df = lf.query('id > 1000').collect()
# Other formats
df_parquet = npd.read_parquet('data.parquet')
df_excel = npd.read_excel('data.xlsx')
df_json = npd.read_json('data.json')
Data Operations
# GroupBy operations
result = df.groupby('city')['age'].mean()
result = df.groupby(['city', 'category'])['value'].sum()
result = df.groupby('category').agg({'value': 'mean', 'count': 'sum'})
# Sorting, filtering, sampling
df_sorted = df.sort_values('age', ascending=False)
df_filtered = df.query("age > 25 and city == 'Paris'")
df_sample = df.sample(n=1000, random_state=42)
# Top-N rows
top10 = df.nlargest(10, 'age')
# Pivot table
pivot = df.pivot_table(values='age', index='city', aggfunc='mean')
# Summary statistics
df.describe()
df.std()
df.median()
df.corr()
Writing Files
df.to_csv('output.csv')
df.to_parquet('output.parquet')
df.to_json('output.json')
df.to_excel('output.xlsx')
๐ฌ profile_compare
profile_compare runs your pandas code line-by-line under both backends and reports the speedup per line โ so you know exactly where nitro-pandas helps.
import nitro_pandas as npd
def my_pipeline(pd):
df = pd.read_csv("data.csv")
df = df.rename(columns={"review/score": "score"})
result = df.groupby("Id")["score"].mean()
return result
print(npd.profile_compare(my_pipeline))
Output:
------------------------------------------------------------------------------------------
Line Source pandas nitro Gain
------------------------------------------------------------------------------------------
5 df = pd.read_csv("data.csv") 13.0385s 1.0866s 12.00x โ
6 df = df.rename(columns={"review/score": "sco 0.1051s 0.0013s 80.14x โ
7 result = df.groupby("Id")["score"].mean() 0.0296s 0.0039s 7.51x โ
------------------------------------------------------------------------------------------
TOTAL 13.1732s 1.0918s 12.07x
------------------------------------------------------------------------------------------
Options:
npd.profile_compare(
my_pipeline,
n_runs=3, # average over 3 runs
warmup=1, # 1 warm-up run discarded
assert_equal=True, # raise if results differ between backends
return_format="dataframe", # "table" (default) | "dict" | "dataframe"
)
Lines marked โ triggered a pandas fallback โ those are candidates for native implementation.
๐ API Reference
DataFrame Operations
Creation
df = npd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
df = npd.DataFrame(pl.DataFrame({'a': [1, 2, 3]}))
Indexing
df['column_name'] # Returns nitro-pandas Series
df[['col1', 'col2']] # Returns DataFrame
df[df['age'] > 30] # Boolean filtering
df.loc[df['age'] > 30, 'name']
df.iloc[0:5, 0:2]
Transformations
df.astype({'id': 'int64', 'name': 'str'})
df.rename(columns={'old': 'new'})
df.drop(labels=['col1'], axis=1)
df.fillna({'column': 0})
df.sort_values('age', ascending=False)
df.drop_duplicates(subset=['id'])
Aggregations (native, no pandas fallback)
df.describe()
df.std()
df.median()
df.corr()
df.groupby('col')['val'].mean()
df.groupby('col')['val'].count()
df.nlargest(100, 'col')
df.sample(n=1000, random_state=42)
df.pivot_table(values='val', index='col', aggfunc='mean')
I/O Functions
CSV
df = npd.read_csv('file.csv', sep=',', usecols=['col1', 'col2'], dtype={'id': 'int64'})
lf = npd.read_csv_lazy('file.csv', n_rows=1000)
Parquet
df = npd.read_parquet('file.parquet', columns=['col1', 'col2'])
lf = npd.read_parquet_lazy('file.parquet')
Excel
df = npd.read_excel('file.xlsx', sheet_name=0, usecols=['col1'], nrows=1000)
lf = npd.read_excel_lazy('file.xlsx', sheet_name='Sheet1')
JSON
df = npd.read_json('file.json', dtype={'id': 'int64'})
lf = npd.read_json_lazy('file.json', lines=True)
๐ Migration from pandas
# Before
import pandas as pd
df = pd.read_csv('data.csv')
result = df.groupby('category')['value'].mean()
# After โ same code, faster execution
import nitro_pandas as npd
df = npd.read_csv('data.csv')
result = df.groupby('category')['value'].mean()
Key differences to be aware of:
df['col']returns a nitro-pandasSeries(not a pandas Series) โ it's compatible with boolean indexing and most pandas operations- No
inplaceparameter โ all operations return new DataFrames - No mixed column types โ each column must have a consistent type (Polars requirement)
- Unimplemented methods fall back to pandas automatically with a
PandasFallbackWarning
import warnings
from nitro_pandas import PandasFallbackWarning
# Silence fallback warnings if needed
warnings.filterwarnings("ignore", category=PandasFallbackWarning)
๐๏ธ Project Structure
nitro-pandas/
โโโ nitro_pandas/
โ โโโ __init__.py # Public API
โ โโโ dataframe.py # DataFrame, Series, GroupBy
โ โโโ profiling.py # profile_compare
โ โโโ lazyframe.py # LazyFrame
โ โโโ io/ # read_csv, read_parquet, read_excel, read_json
โโโ tests/
โ โโโ test_dataframe.py
โ โโโ test_profiling.py
โ โโโ test_groupby.py
โ โโโ test_io.py
โ โโโ test_runner.py
โโโ pyproject.toml
โโโ CHANGELOG.md
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes
- Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Development Setup
git clone https://github.com/Wassim17Labdi/nitro-pandas.git
cd nitro-pandas
uv sync --dev
uv run python tests/test_runner.py
๐ License
This project is licensed under the MIT License โ see the LICENSE file for details.
๐ Acknowledgments
- Polars โ For the high-performance DataFrame engine
- pandas โ For the API inspiration and fallback support
Made with โค๏ธ for the Python data science community
โญ Star this repo if you find it useful!
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nitro_pandas-0.2.0.tar.gz.
File metadata
- Download URL: nitro_pandas-0.2.0.tar.gz
- Upload date:
- Size: 1.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a0b17dda7bb4d9ed100af937d6ceea0d6c79ea6739a7381d8de80f3529d53e6
|
|
| MD5 |
4dd369125a2e747fa4ab4c546e18834e
|
|
| BLAKE2b-256 |
a3199dcd12143c7827c409557a1914967d3fffa81fdded5eadf30386e001179f
|
Provenance
The following attestation bundles were made for nitro_pandas-0.2.0.tar.gz:
Publisher:
publish.yml on Wassim17Labdi/nitro-pandas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nitro_pandas-0.2.0.tar.gz -
Subject digest:
3a0b17dda7bb4d9ed100af937d6ceea0d6c79ea6739a7381d8de80f3529d53e6 - Sigstore transparency entry: 1575551705
- Sigstore integration time:
-
Permalink:
Wassim17Labdi/nitro-pandas@a0f8e4f7b09c2f043e04bf953e65513c75faa6a1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Wassim17Labdi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a0f8e4f7b09c2f043e04bf953e65513c75faa6a1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file nitro_pandas-0.2.0-py3-none-any.whl.
File metadata
- Download URL: nitro_pandas-0.2.0-py3-none-any.whl
- Upload date:
- Size: 33.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d066ebf9cf8f6495a20f51d6faf3fff7fd51a8d7520e04b98f4c8a5485066de9
|
|
| MD5 |
ed3472da4be0b4d18f1eac43498d4551
|
|
| BLAKE2b-256 |
20da40b85bc87e978f70c0bd44f404bb315dcd5a5fd733a9a3ce92b012e8301a
|
Provenance
The following attestation bundles were made for nitro_pandas-0.2.0-py3-none-any.whl:
Publisher:
publish.yml on Wassim17Labdi/nitro-pandas
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nitro_pandas-0.2.0-py3-none-any.whl -
Subject digest:
d066ebf9cf8f6495a20f51d6faf3fff7fd51a8d7520e04b98f4c8a5485066de9 - Sigstore transparency entry: 1575551743
- Sigstore integration time:
-
Permalink:
Wassim17Labdi/nitro-pandas@a0f8e4f7b09c2f043e04bf953e65513c75faa6a1 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Wassim17Labdi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@a0f8e4f7b09c2f043e04bf953e65513c75faa6a1 -
Trigger Event:
release
-
Statement type: