Skip to main content

bandas banner

PyPI version Python versions License GitHub stars CI

bandas — pandas-compatible DataFrames, at full speed ⚡

bandas is a pandas-compatible DataFrame library (same API names: DataFrame, Series, read_csv, concat, merge, …) with a faster execution engine — plus a complete data platform for databases, time series, feature preprocessing, machine learning, deep learning and visualization. Built for developers, data analysts, data scientists and ML engineers.

Why bandas?

  1. Pure columnar NumPy storage — no BlockManager overhead, no per-op index alignment.
  2. Numeric fast paths — sum/mean/min/max straight through NumPy, bincount-powered groupby.
  3. Optional Numba + PyArrow acceleration — compiled groupby kernels, 3–5x faster CSV reads.
  4. Real SQL built in — df.sql("SELECT …") with zero extra dependencies (embedded SQLite), plus a unified Database connector for SQLite / DuckDB / Postgres / MySQL / SQLAlchemy.
  5. ML/DL ready — train_test_split, KFold, metrics, StandardScaler, OneHotEncoder, to_torch, to_tensorflow, dataset loaders.
  6. Advanced analytics — rolling/expanding/ewm, shift/diff/pct_change, pivot_table/melt/crosstab, str/dt accessors, and LazyFrame for out-of-core files.

Install

One command installs everything (speed + databases + ML + plotting + Excel):

pip install bandas-df

From source:

git clone https://github.com/salim-studio/bandas.git
cd bandas
pip install -e .

Deep-learning frameworks only (torch and tensorflow are gigabytes in size and have no wheels for the newest Python versions):

pip install "bandas-df[dl]"

Quickstart

import bandas as bd

df = bd.DataFrame({"a": [1, 2, 3], "b": [4.0, 5.0, 6.0]})
print(df.head())
print(df["a"].sum())

df2 = bd.read_csv("data.csv")  # uses PyArrow when available
g = df2.groupby("city")["price"].mean()
print(g.to_pandas())

# Full pandas interop whenever you need it
pdf = df.to_pandas()
df3 = bd.from_pandas(pdf)

On 500k rows bandas is faster than pandas across the board (sum ~1.9x, mean ~2.6x, groupby ~1.4x — see bench/bench.py).

Databases / SQL

# Zero-setup SQL — always works (embedded SQLite)
top = df.sql("SELECT city, AVG(price) AS m FROM df GROUP BY city ORDER BY m DESC")

# Query across several frames
from bandas import sql_query
out = sql_query("SELECT * FROM a JOIN b ON a.k = b.k WHERE a.v > 10", {"a": a, "b": b})

# Unified connector
from bandas.sql import Database
db = Database.sqlite("app.db")  # or ":memory:"
# db = Database.duckdb("data.duckdb")        # needs duckdb
# db = Database.postgres(user=..., password=..., host=..., db=...)
db.write(df, "sales")
print(db.query("SELECT COUNT(*) AS n FROM sales").to_pandas())
print(db.tables())

# pandas-style API
df.to_sql("sales", "sqlite:///app.db")
df2 = bd.read_sql("SELECT * FROM sales", "sqlite:///app.db")

Time series & windows

s = df["price"]
s.rolling(7).mean()    # moving average
s.expanding().sum()
s.ewm(span=10).mean()
s.shift(1); s.diff(); s.pct_change(); s.cumsum()
df.rolling(30).mean(); df.ewm(alpha=0.3).mean()

bd.to_datetime(["2024-01-01", "2024-02-01"])
bd.date_range("2024-01-01", periods=12, freq="ME")
df["d"].dt.year / .month / .day / .dayofweek

Strings, categories & reshaping

df["name"].str.lower().str.strip().str.contains("ali")
df["name"].str.replace("a", "@").str.split(" ", expand=True)
bd.get_dummies(df, columns=["city"])
bd.melt(df, id_vars=["city"])
bd.pivot_table(df, values="price", index="city", columns="year", aggfunc="mean")
bd.crosstab(df["city"], df["year"])
bd.cut(df["age"], bins=[0, 18, 60, 100])
bd.qcut(df["price"], 4)

Preprocessing

bd.SimpleImputer(strategy="mean").fit_transform(df)
bd.StandardScaler().fit_transform(df)
bd.MinMaxScaler().fit_transform(df)
bd.RobustScaler().fit_transform(df)
bd.LabelEncoder().fit_transform(df["city"])
bd.OneHotEncoder(columns=["city"]).fit_transform(df)

Machine learning

X_train, X_test, y_train, y_test = bd.train_test_split(X, y, test_size=0.2, random_state=0)
list(bd.KFold(n_splits=5).split(X))
bd.accuracy_score(y, pred); bd.f1_score(y, pred)
bd.mean_squared_error(y, pred); bd.r2_score(y, pred)

# Drop straight into scikit-learn
from sklearn.ensemble import RandomForestClassifier
clf = RandomForestClassifier().fit(X_train_numpy, y_train_numpy)

Deep learning

X_t, y_t = df.to_torch(target="label")     # torch.Tensor
loader = bd.dl.torch_dataset(df, target="label", batch_size=64)
ds = bd.dl.tf_dataset(df, target="label")  # tf.data.Dataset

Large files (lazy / out-of-core)

lf = bd.read_csv_chunked("big.csv", chunksize=100_000)
out = lf.filter(lambda d: d[d["x"] > 0]).select(["x", "y"]).collect()
print(lf.sum("x"), lf.mean("x"), lf.count())

Quick plotting

df.plot(kind="line", x="date", y="price")
df.plot(kind="bar", x="city", y="sales")
df["price"].hist(bins=50)
bd.viz.scatter(df, "a", "b"); bd.viz.heatmap_corr(df)

Full IO coverage

read_csv / read_parquet / read_json / read_excel / read_html / read_feather / read_orc / read_sql + to_csv / to_parquet / to_json / to_excel / to_sql — all with pandas-compatible signatures.

Project layout

bandas/
  __init__.py      # public API + concat/merge/options/show_versions
  series.py        # Series + str/dt + rolling/ewm + cum*/shift/diff
  dataframe.py     # DataFrame + SQL + stats + reshape + viz + torch
  groupby.py       # fast GroupBy + std/var/median/first/last/nunique
  io.py            # every file reader + chunked
  sql.py           # sql_query + read_sql/to_sql + unified Database
  reshape.py       # get_dummies/melt/pivot/crosstab/cut/qcut
  window.py        # Rolling/Expanding/EWM
  strings.py       # Series.str
  datetimes.py     # Series.dt + to_datetime/date_range
  preprocessing.py # Imputer/Scaler/Encoder
  ml.py            # split/CV/metrics/sklearn bridge
  dl.py            # torch/tensorflow bridges
  stats.py         # corr/cov/outliers/summary
  lazy.py          # out-of-core LazyFrame
  viz.py           # quick charts
  ops.py / utils.py
assets/            # logo + banner
tests/             # 20 tests
bench/bench.py     # bandas vs pandas benchmark

Test & benchmark

pytest -q
python bench/bench.py
python -c "import bandas; bandas.show_versions()"

Changelog

See CHANGELOG.md.

License

MIT — see LICENSE.

Metadata

Release files for bandas-df 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bandas-df 0.4.0
File Size Uploaded Provenance
bandas_df-0.4.0.tar.gz 43.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for bandas-df 0.4.0
File Interpreter ABI Platform
bandas_df-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 86.3 kB

Release files / bandas_df-0.4.0.tar.gz

Download URL bandas_df-0.4.0.tar.gz
Size 43.6 kB
Tags Source
SHA-256 checksum
How to use checksums
2f5e172a6377b67b3105117d38ba6ae6fc9b49998a12c75aa7140d09c3436408
BLAKE2b-256 checksum
How to use checksums
8f0b942dae96be50a216463a76e60d5317bbc678110309ac6d227fa988435af1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Release files / bandas_df-0.4.0-py3-none-any.whl

Download URL bandas_df-0.4.0-py3-none-any.whl
Size 42.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5bffc8dec708c3d43a944ed970325139d94e59ccb9059992b27af81bf9ea6ffc
BLAKE2b-256 checksum
How to use checksums
db1ce8e783d67e1a2b20231c4d606be8e93f21451179717f5ca5a3c5a76930a6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.7

Security for bandas-df 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page