A pandas-like library built on Rust
Project description
rspandas
A pandas-like library built on Rust — familiar pandas API, Rust-powered performance.
import rspandas as rpd
df = rpd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
print(df.describe())
print(df.groupby("a").sum())
Features
- 95%+ pandas API compatibility — drop-in replacement for most use cases
- Rust backend — columnar storage, vectorized operations, near-native performance
- Zero runtime dependencies — pure Python + compiled Rust extension
- Rich I/O — CSV, Excel, Parquet, JSON, SQL, Pickle, Feather
- Full type system — int64, float64, bool, string, category, datetime, timedelta, period
- Comprehensive test suite — 950+ tests covering all major APIs
Installation
Requires Python >= 3.9.
pip install -e .
Or build from source:
maturin build --release
pip install target/wheels/rspandas-*.whl
Quick Start
Series
import rspandas as rpd
# Create
s = rpd.Series([1, 2, 3, 4, 5], name="values")
# Basic ops
s.head(3) # first 3 rows
s.sum() # 15
s.mean() # 3.0
s.std() # ~1.58
s.describe() # summary stats
# Missing values
s2 = rpd.Series([1, None, 3])
s2.fillna(0) # replace None with 0
s2.dropna() # remove None rows
# String operations
s3 = rpd.Series(["hello", "world"])
s3.str.upper() # ["HELLO", "WORLD"]
s3.str.contains("ell") # [True, False]
DataFrame
import rspandas as rpd
# Create
df = rpd.DataFrame({
"name": ["Alice", "Bob", "Charlie"],
"age": [25, 30, 35],
"score": [88.5, 92.0, 79.3],
})
# Properties
df.shape # (3, 3)
df.columns # ["name", "age", "score"]
df.dtypes # {"name": "object", "age": "int64", "score": "float64"}
# Subsetting
df.head(2) # first 2 rows
df["age"] # Series
df[["name", "score"]] # DataFrame with selected columns
# Filtering
df[df["age"] > 26] # rows where age > 26
# Sorting
df.sort_values("score", ascending=False)
GroupBy
df = rpd.DataFrame({
"team": ["A", "A", "B", "B", "C"],
"score": [10, 20, 30, 40, 50],
})
df.groupby("team").sum() # sum by group
df.groupby("team").mean() # mean by group
df.groupby("team").agg("std") # std by group
df.groupby("team").cumcount() # cumulative count
df.groupby("team").rank() # rank within group
Window Functions
s = rpd.Series([1, 2, 3, 4, 5])
s.rolling(3).mean() # [None, None, 2.0, 3.0, 4.0]
s.rolling(3).sum() # [None, None, 6.0, 9.0, 12.0]
s.rolling(3).std() # rolling std
s.expanding().mean() # expanding window
s.expanding().sum() # [1.0, 3.0, 6.0, 10.0, 15.0]
s.ewm(span=3).mean() # exponentially weighted
Time Series
import rspandas as rpd
dates = rpd.date_range("2024-01-01", periods=5, freq="D")
ts = rpd.Series([1, 2, 3, 4, 5], index=dates)
ts.shift(1) # lag
ts.diff() # difference
ts.pct_change() # percent change
ts.cumsum() # [1, 3, 6, 10, 15]
# DatetimeSeries
ds = rpd.to_datetime(["2024-01-15", "2024-06-15"])
ds.dt.year # [2024, 2024]
ds.dt.month # [1, 6]
ds.dt.dayofweek # [0, 5] (Monday=0)
ds.dt.month_name # ["January", "June"]
Reshape
# Melt (wide to long)
df = rpd.DataFrame({"a": [1, 2], "b": [3, 4]})
df.melt(id_vars=["a"])
# Pivot (long to wide)
df = rpd.DataFrame({
"x": ["a", "a", "b"],
"y": ["p", "q", "p"],
"v": [1, 2, 3],
})
df.pivot(index="x", columns="y", values="v")
# Stack / Unstack
df.stack()
df.transpose() # or df.T
I/O
import rspandas as rpd
# CSV
df = rpd.read_csv("data.csv")
df.to_csv("output.csv")
# Excel
df = rpd.read_excel("data.xlsx")
df.to_excel("output.xlsx")
# Parquet
df = rpd.read_parquet("data.parquet")
df.to_parquet("output.parquet")
# JSON
df = rpd.read_json("data.json")
df.to_json("output.json")
# SQL
df = rpd.read_sql("sqlite:///db.sqlite", "SELECT * FROM table")
df.to_sql("sqlite:///db.sqlite", "table_name")
# Pickle
df = rpd.read_pickle("data.pkl")
df.to_pickle("output.pkl")
Merge & Concat
df1 = rpd.DataFrame({"key": ["a", "b", "c"], "v1": [1, 2, 3]})
df2 = rpd.DataFrame({"key": ["b", "c", "d"], "v2": [4, 5, 6]})
df1.merge(df2, on="key", how="inner") # inner join
df1.merge(df2, on="key", how="left") # left join
df1.merge(df2, on="key", how="outer") # outer join
rpd.concat([df1, df2], axis=0) # row-wise
rpd.concat([df1, df2], axis=1) # column-wise
Interop
# pandas
df.to_pandas()
rpd.DataFrame.from_pandas(pdf)
# numpy
s.to_numpy()
rpd.Series.from_numpy(arr)
# pyarrow
df.to_arrow()
rpd.DataFrame.from_arrow(table)
Utilities
rpd.factorize(["a", "b", "a", "c"]) # (codes, categories)
rpd.to_numeric(["1", "2", "x"], errors="coerce") # [1, 2, None]
rpd.get_dummies(df)
rpd.cut(s, bins=[0, 10, 20, 30])
rpd.qcut(s, q=4)
rpd.crosstab(df["a"], df["b"])
Options
rpd.set_option("display.max_rows", 100)
rpd.set_option("display.max_columns", 50)
rpd.get_option("display.width") # 80
rpd.reset_option("all")
API Coverage
Top-level Functions
read_csv, to_csv, read_excel, to_excel, read_parquet, to_parquet, read_json, to_json, read_sql, to_sql, read_pickle, to_pickle, read_feather, to_feather, concat, merge, get_dummies, cut, qcut, crosstab, factorize, to_datetime, to_timedelta, to_numeric, date_range, timedelta_range, period_range, bdate_range, infer_freq, set_option, get_option, reset_option
Series
Properties: shape, dtype, name, values, index, size, empty
Accessors: .str, .dt, .cat
Methods: head, tail, sum, mean, min, max, count, std, var, median, describe, isnull, notnull, dropna, fillna, unique, nunique, value_counts, astype, sort_values, sort_index, apply, map, replace, where, mask, duplicated, drop_duplicates, isin, between, rolling, expanding, ewm, resample, shift, diff, pct_change, cumsum, cumprod, cummax, cummin, rank, quantile, argmax, argmin, idxmax, idxmin, explode, repeat, to_list, to_numpy, to_dict, to_frame, to_pandas, from_pandas, mode, skew, kurt, sem, abs, round, clip, rename, rename_axis, iloc, loc
DataFrame
Properties: shape, columns, dtypes, index, values, size, empty, T
Methods: head, tail, describe, info, dropna, fillna, merge, concat, groupby, apply, applymap, sort_values, sort_index, sort_columns, set_index, reset_index, reindex, drop, rename, rename_axis, replace, duplicated, drop_duplicates, melt, pivot, pivot_table, stack, unstack, transpose, swapaxes, rolling, expanding, ewm, resample, shift, diff, pct_change, cumsum, cumprod, cummax, cummin, rank, quantile, mode, skew, kurt, idxmax, idxmin, clip, astype, select_dtypes, filter, assign, eval, query, pipe, transform, take, xs, get, compare, equals, copy, pop, insert, first, last, truncate, asfreq, tz_localize, tz_convert, between_time, at_time, first_valid_index, last_valid_index, nunique, memory_usage, cumcount, to_pandas, from_pandas, to_numpy, from_numpy, to_arrow, from_arrow, iloc, loc
String Accessor
lower, upper, title, capitalize, swapcase, casefold, strip, lstrip, rstrip, len, contains, startswith, endswith, replace, split, rsplit, slice, cat, find, rfind, findall, match, fullmatch, extract, extractall, partition, rpartition, wrap, zfill, pad, isalnum, isalpha, isdigit, islower, isupper, isspace, istitle, encode, decode, get, count, ljust, rjust, center, slice_replace, get_dummies
Datetime Accessor
year, month, day, hour, minute, second, microsecond, dayofweek, dayofyear, quarter, is_month_start, is_month_end, is_year_start, is_year_end, is_leap_year, days_in_month, day_name, month_name, strftime, to_pydatetime
Index Types
Index, RangeIndex, MultiIndex, IntervalIndex, DatetimeIndex, TimedeltaIndex, PeriodIndex, CategoricalIndex
Architecture
User Code (Python)
|
| import rspandas as rpd
v
+----------------------------------------+
| python/rspandas/ | <-- Python API layer
| series.py / dataframe.py / ... | (pandas-compatible signatures)
+----------------------------------------+
| PyO3 FFI
v
+----------------------------------------+
| rspandas._rust (compiled .so/.dylib) | <-- Native module
+----------------------------------------+
| PySeries / PyDataFrame (#[pyclass]) |
+----------------------------------------+
| Series / DataFrame (Rust structs) | <-- Rust core
+----------------------------------------+
| ColumnData (Int/Float/Bool/String) |
+----------------------------------------+
- Python layer: parameter validation, type inference, formatted display, API compatibility
- Rust core: columnar storage, vectorized computation, filtering, aggregation
- PyO3 bridge: zero-copy Python/Rust type conversion
Development
# Install in dev mode
pip install -e .
# Run tests
pytest tests/ # 950+ Python tests
cargo test # Rust unit tests
# Lint
cargo clippy
cargo fmt
Requirements
- Python >= 3.9
- Rust toolchain (stable)
- maturin >= 1.7
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
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 rspandas-2.0.1.tar.gz.
File metadata
- Download URL: rspandas-2.0.1.tar.gz
- Upload date:
- Size: 119.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a469ca8701e40f58b3200ae4e6bcfe00dc333992fdb5e17b04c444c0459abd0b
|
|
| MD5 |
0c170e16e342966b300774f18fec9ab3
|
|
| BLAKE2b-256 |
7036296ed8469ae665b334a6f64dfde09435c8449f32987bd1d25c55eff20d67
|
File details
Details for the file rspandas-2.0.1-cp313-cp313-macosx_11_0_arm64.whl.
File metadata
- Download URL: rspandas-2.0.1-cp313-cp313-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.4 MB
- Tags: CPython 3.13, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7816f4e9e768f4985be7d2fbdc8e4a7eee515869b4cef25e09ce420eba5a5aad
|
|
| MD5 |
2808be8dee2b4d475eb05e46cb956cf0
|
|
| BLAKE2b-256 |
3b84204056b2a7cd9f6ddfc97fda25492582371ce233aaaaa63c519f0a821a23
|
File details
Details for the file rspandas-2.0.1-cp313-cp313-macosx_10_12_x86_64.whl.
File metadata
- Download URL: rspandas-2.0.1-cp313-cp313-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.5 MB
- Tags: CPython 3.13, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b25c1c1a4a1af025e254119915efbd5a3f5d3093d3befcaa00e2320e8c69b18
|
|
| MD5 |
bd2432540e0827ddff72db17025e1ac5
|
|
| BLAKE2b-256 |
dbba45f067c65401f50c3dfbed39ca53fb4e3eca8aebb43dabe4508d1e9a9043
|