Skip to main content

A pandas-like library built on Rust

Project description

rspandas

pandas-compatible API, Rust-powered performance

PyPI Python CI License


rspandas is a drop-in pandas replacement with a Rust backend. Write the same pandas code you know—filtering, grouping, window functions, reshaping—but get near-native performance thanks to columnar storage, vectorized operations, and multi-threaded parallelism via Rayon.

import rspandas as rpd

df = rpd.DataFrame({"a": [1, 2, 3], "b": ["x", "y", "z"]})
print(df.describe())
print(df.groupby("a").sum())

Highlights

  • 95%+ pandas API coverage — Series, DataFrame, GroupBy, window functions, reshaping, time series
  • Rust core — columnar storage, vectorized computation, Rayon parallel iterators
  • Multi-platform wheels — pre-built binaries for Linux (x86_64 / arm64), macOS (Intel / Apple Silicon), Windows (x64 / x86)
  • Zero required Python dependencies — one compiled extension, no NumPy/PyArrow required at runtime
  • Rich I/O — CSV, Excel (native Rust), JSON, Parquet, SQL, Pickle, Feather
  • Full type system — int64, float64, bool, string, category, datetime, timedelta, period
  • 950+ tests — comprehensive pytest suite validating pandas compatibility

Installation

Requires Python >= 3.9.

pip install rspandas

Or build from source:

pip install maturin
maturin build --release
pip install target/wheels/rspandas-*.whl

Quick Start

Series

import rspandas as rpd

s = rpd.Series([1, 2, 3, 4, 5], name="values")
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 → 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

df = rpd.DataFrame({
    "name": ["Alice", "Bob", "Charlie"],
    "age":  [25, 30, 35],
    "score": [88.5, 92.0, 79.3],
})

df.shape            # (3, 3)
df.dtypes           # {"name": "object", "age": "int64", "score": "float64"}
df.head(2)
df["age"]           # Series
df[df["age"] > 26]  # filter rows
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").rank()      # rank within group

Window Functions

s = rpd.Series([1, 2, 3, 4, 5])

s.rolling(3).mean()    # [NaN, NaN, 2.0, 3.0, 4.0]
s.rolling(3).sum()     # [NaN, NaN, 6.0, 9.0, 12.0]
s.expanding().sum()    # [1.0, 3.0, 6.0, 10.0, 15.0]
s.ewm(span=3).mean()   # exponentially weighted

Time Series

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_name  # ["January", "June"]

I/O

# CSV (native Rust)
df = rpd.read_csv("data.csv")
df.to_csv("output.csv")

# Excel (native Rust via calamine + rust_xlsxwriter)
df = rpd.read_excel("data.xlsx")
df.to_excel("output.xlsx")

# JSON
df = rpd.read_json("data.json")
df.to_json("output.json")

# Parquet / Feather (requires pyarrow)
df = rpd.read_parquet("data.parquet")
df.to_parquet("output.parquet")
df = rpd.read_feather("data.feather")

# SQL (requires sqlalchemy)
df = rpd.read_sql("SELECT * FROM table", engine)
df.to_sql("table_name", engine)

# Pickle
df = rpd.read_pickle("data.pkl")
df.to_pickle("output.pkl")

Merge & Reshape

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
rpd.concat([df1, df2], axis=0)          # row-wise

# Melt / Pivot
df.melt(id_vars=["a"])
df.pivot(index="x", columns="y", values="v")

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.crosstab(df["a"], df["b"])

Performance

rspandas leverages multi-threaded parallelism via Rayon across all heavy operations:

Operation Parallelized methods
Aggregation sum, mean, min, max, std, var, nunique, any, all
Filtering filter, dropna, isnull, notnull, fillna
I/O CSV type inference & parsing, XLSX column conversion
DataFrame head, tail, filter_rows, dropna_rows, fillna_rows, to_string
String conversion to_string_vec, columns_to_string

The Rust core uses columnar Vec<Option<T>> storage with opt-level=3 and lto=true in release builds.

Architecture

User Code (Python)
    │  import rspandas as rpd
    ▼
┌──────────────────────────────────────┐
│  python/rspandas/                    │  ← Python API layer
│  series.py / dataframe.py / ...      │     (pandas-compatible signatures)
└────────────────┬─────────────────────┘
                 │  PyO3 FFI
                 ▼
┌──────────────────────────────────────┐
│  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, display formatting, API compatibility
  • Rust core: columnar storage, vectorized computation, parallel filtering & aggregation
  • PyO3 bridge: zero-copy Python/Rust type conversion

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, nbytes

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

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rspandas-2.0.2.tar.gz (120.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rspandas-2.0.2-cp313-cp313-macosx_11_0_arm64.whl (1.4 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

rspandas-2.0.2-cp313-cp313-macosx_10_12_x86_64.whl (1.5 MB view details)

Uploaded CPython 3.13macOS 10.12+ x86-64

File details

Details for the file rspandas-2.0.2.tar.gz.

File metadata

  • Download URL: rspandas-2.0.2.tar.gz
  • Upload date:
  • Size: 120.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.14.0

File hashes

Hashes for rspandas-2.0.2.tar.gz
Algorithm Hash digest
SHA256 4246ab663d6c0c29981cff7bada214998b2c2f49408c3dc4809f5cdb4cf3e25a
MD5 05c9cf23f7b2c9fdecf461672274e8e7
BLAKE2b-256 69837be645f125b224e30a8614fb64b762e6b1ef1666e8d5ebd7dde3f1b993de

See more details on using hashes here.

File details

Details for the file rspandas-2.0.2-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rspandas-2.0.2-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d0259311804c0063aeafd4cb355638abb302231694646139f3e7bb8a7e3e3640
MD5 49bb54fa4ba8c376861e63a1417de1d5
BLAKE2b-256 9b185fc9c0aa5be9481742d81bdd497bfe8937bb5c26922963539c59e50a83e4

See more details on using hashes here.

File details

Details for the file rspandas-2.0.2-cp313-cp313-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for rspandas-2.0.2-cp313-cp313-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a458c6d709f0dd0d9e29c4f7c1ca1f01d0cd0c55c96efb51fb4c136975bebb85
MD5 d991bf57fbba28469e15c90978ef4a00
BLAKE2b-256 63f8b85d8beafee22876dd070ec32d16440bfd4079e674770a18c649dbb75993

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page