pandasx
v0.1.6
Published
pandas-like DataFrame and Series for Node.js, written in TypeScript
Maintainers
Readme
pandasx
pandas-style Series and DataFrame for Node.js, written in TypeScript.
📖 Documentation: gftf2011.github.io/pandasx — getting started, coming from pandas, guides with runnable examples and the full API reference.
🧪 Examples: 20 runnable scripts covering every feature, from Series basics to an end-to-end sales report.
- Columnar, typed storage: numbers and dates in
Float64Array, booleans inUint8Array, categories inInt32Array. - Faithful to the pandas API, with camelCase names (
sort_values→sortValues,read_csv→readCsv). - Checked against real pandas: 214 parity cases (
npm run parity) plus fixtures written by pandas 3.1. - No required dependencies. Excel, Parquet, Feather and HDF5 use optional packages that only the people who need them install.
npm install pandasxRequires Node.js 22.23.4+, 24.22.1+ or 26.12.1+: earlier releases have a Brotli decoder vulnerable to CVE-2026-111497 (Node2Shell).
Example
import * as pd from 'pandasx';
const df = new pd.DataFrame({
region: ['SP', 'RJ', 'SP', 'MG', 'RJ', 'SP'],
product: ['coffee', 'coffee', 'tea', 'coffee', 'tea', 'coffee'],
quantity: [10, 4, 0, 7, 12, 25],
price: [12.5, 13, 8, 11.9, 7.5, 12.5],
});
// or: const df = pd.readCsv('sales.csv', { parseDates: ['date'] });
const summary = df
.query('quantity > 0')
.assign({ revenue: (d) => d.get('quantity').mul(d.get('price')) })
.groupby('region')
.agg({ revenue: 'sum', quantity: ['mean', 'max'] })
.sortValues(['revenue', 'sum']);
console.log(summary);
// revenue quantity
// sum mean max
// region
// MG 83.3 7.0 7
// RJ 142.0 8.0 12
// SP 437.5 17.5 25From pandas to pandasx
Python overloads [] and operators. JavaScript can't, so those forms become methods:
| pandas (Python) | pandasx |
|---|---|
| df['a'], df[['a','b']], df[mask] | df.get('a'), df.get(['a','b']), df.get(mask) |
| df['c'] = v | df.set('c', v) |
| df.loc['x', 'a'], df.loc['x':'z'] | df.loc('x', 'a'), df.loc(pd.slice('x', 'z')) |
| df.loc[mask, 'a'] = 0 | df.setLoc(mask, 'a', 0) (also setIloc, setAt, setIat) |
| s + 1, s == 1, (a > 1) & ~b | s.add(1), s.eq(1), a.gt(1).and(b.not()) |
| df.query('a > 1 and b == "x"') | df.query('a > 1 and b == "x"') (same syntax) |
| df.groupby('k')['v'].sum() | df.groupby('k').get('v').sum() |
| df[('price', 'min')] (MultiIndex columns) | df.column(['price', 'min']) |
| pd.option_context('display.precision', 2) | pd.optionContext({ 'display.precision': 2 }, () => ...) |
| df.plot.bar() (matplotlib) | df.plot.bar() → SVG |
The complete mapping is in Coming from pandas.
Features
Each area has a guide with examples whose output is generated by running them:
| Area | Highlights | Guide |
|---|---|---|
| Data structures & dtypes | int64, float64, bool, nullable Int64 / Float64 / boolean, string, category, tz-aware datetime, timedelta, period, bigint | Data structures |
| Selection & assignment | get, loc, iloc, at, iat, xs, set*, query / eval strings | Selecting |
| Missing data | isna, fillna, dropna, ffill / bfill, interpolate (linear … akima) | Missing data |
| Computation | aggregations, quantile, rank, corr (Pearson / Spearman / Kendall), describe, valueCounts | Computation |
| Text & categories | full .str and .cat accessors | Text & categories |
| Group by | agg, named aggregation, transform, filter, apply, per-group windows | Group by |
| Reshaping | MultiIndex, stack / unstack, pivotTable, crosstab, melt, getDummies, cut / qcut, explode | Reshaping |
| Combining | merge, join, concat, mergeAsof, mergeOrdered, combineFirst, update, compare | Combining data |
| Time series | toDatetime, dateRange, offsets, time zones, .dt, resample, rolling, expanding, ewm | Time series |
| Input / output | CSV, JSON, HTML, XML, SQL, Excel, Parquet, Feather / Arrow, HDF5 | Reading & writing |
| Plotting | SVG line, bar, hist, box, kde, area, pie, scatter, hexbin, subplots | Plotting |
| Styling | df.style: highlights, gradients, bars, Python format specs, HTML / LaTeX | Styling |
| Display | console.log like pandas, setOption, optionContext, info | Display & options |
The binary formats need optional packages, installed only when used: exceljs (Excel), hyparquet + hyparquet-writer (Parquet), apache-arrow (Feather) and h5wasm (HDF5).
Differences from pandas
The main ones: [] and operators become methods, binary I/O is asynchronous, datetimes have millisecond resolution, column labels are unique strings, and plots are SVG with no secondary y axis. The full list is in Differences from pandas.
Performance
Six common operations on 1 million rows against the other JavaScript dataframe libraries (Apple M2, Node.js 24), median time, lower is better:
| Task | pandasx | Arquero | danfo.js | Data-Forge |
|---|---:|---:|---:|---:|
| groupby (1,000 groups) | 132 ms | 202 ms | 701 ms | 3.04 s |
| merge (inner join) | 155 ms | 219 ms | 1.04 s | 527 ms |
| sortValues | 125 ms | 721 ms | 168 s | 2.11 s |
| filter | 38 ms | 41 ms | 512 ms | 112 ms |
| valueCounts | 55 ms | 125 ms | 116 ms | 357 ms |
| readCsv | 1.17 s | 975 ms | 2.32 s | 3.29 s |
pandasx is the fastest at 7 of the 10 tasks (filtering, sorting, group by, joins, arithmetic, statistics, valueCounts); Arquero is faster at CSV parsing and danfo.js at writing CSV. All ten tasks, both sizes and the method are in Benchmarks; the code is in bench/.
Development
npm testnpm run typecheckPANDAS_PYTHON=/path/to/venv/bin/python npm run parityThe parity suite compares every case with real pandas; it needs a Python with pandas, scipy, pyarrow, tables, openpyxl and lxml. parity/fixtures.py regenerates the files in test/fixtures.
cd bench && npm ci && npm run benchThe benchmark compares pandasx with Arquero, danfo.js and Data-Forge; see bench/README.md.
Documentation
The site in docs/ is built with VitePress; the API reference is generated from the source by TypeDoc.
cd docs && npm cinpm run devEvery ```ts run block in the guides is executed and its output written into the ```text block after it. After changing the library or an example, refresh the outputs with npm run examples (in docs/) and commit them: the build (npm run build) fails if any documented output is stale.
Each push to main deploys the site to GitHub Pages through the Docs workflow (.github/workflows/docs.yml); it can also be run by hand from Actions → Docs → Run workflow.
Releasing
Bump version in package.json (e.g. npm version patch), push to main, then run Actions → Publish to npm → Run workflow. The workflow fails if that version is already on npm. It authenticates with npm Trusted Publishing: on npmjs.com the package lists gftf2011/pandasx with workflow publish.yml as its trusted publisher, so no token is stored.
License
MIT
