Skip to content

Benchmarks ​

How fast is pandasx next to other JavaScript dataframe libraries? The benchmark in bench/ runs the same ten operations in each of them, on the same data, and checks that every library computed the same result.

ToolVersionLanguage
pandasx0.1.5TypeScript
Arquero8.0.3JavaScript
danfo.js1.2.0JavaScript
Data-Forge1.10.5JavaScript

Polars (nodejs-polars) is left out on purpose: it is a Rust engine with Node bindings, not a JavaScript library.

Machine: Apple M2 (8 cores, 8 GB), macOS, Node.js 24.21. Times are medians, lower is better, and bold marks the fastest library.

Results ​

100,000 rows ​

TaskpandasxArquerodanfo.jsData-Forge
read_csv107 ms82 ms212 ms247 ms
construct15 ms<0.1 ms21 ms112 ms
filter9.1 ms7.7 ms49 ms12 ms
sort20 ms47 ms2.19 s181 ms
groupby18 ms24 ms91 ms130 ms
merge19 ms22 ms79 ms52 ms
arithmetic0.7 ms3.4 ms95 ms63 ms
stats1.5 ms4.7 ms22 ms31 ms
value_counts7.3 ms12 ms12 ms37 ms
to_csv124 ms85 ms52 ms147 ms

1,000,000 rows ​

TaskpandasxArquerodanfo.jsData-Forge
read_csv1.17 s975 ms2.32 s3.29 s
construct174 ms<0.1 ms294 ms1.11 s
filter38 ms41 ms512 ms112 ms
sort125 ms721 ms168 s2.11 s
groupby132 ms202 ms701 ms3.04 s
merge155 ms219 ms1.04 s527 ms
arithmetic17 ms19 ms1.10 s1.05 s
stats32 ms34 ms196 ms235 ms
value_counts55 ms125 ms116 ms357 ms
to_csv1.26 s949 ms574 ms2.12 s

Reading the numbers ​

  • pandasx is the fastest at 7 of the 10 tasks at 1 million rows: filtering, sorting, group by, joins, arithmetic, statistics and valueCounts. Its typed columns (Float64Array, Uint8Array masks, category codes) are processed by plain loops, and single-key sorts use a radix sort, 5.8× faster than Arquero's.
  • Arquero leads at CSV parsing (1.0 s against 1.2 s) and at construct, which is almost free in Arquero because aq.table() uses the given arrays without copying them. pandasx copies them into typed columns.
  • danfo.js is the fastest at to_csv, but slows down sharply with size elsewhere: it took 168 s to sort 1 million rows.
  • Data-Forge's row-at-a-time objects make group by and arithmetic 20–60× slower than pandasx.

The tasks ​

TaskWhat it does
read_csvparse the CSV file into a frame
constructbuild a frame from six JavaScript arrays
filterrows where x > 0.5 and cat == 'c3'
sortsort all rows by x
groupbygroup by key (1,000 groups), sum of x and mean of y
mergeinner join with a 1,000-row lookup table on key
arithmeticnew column z = x * y + n
statsmean and standard deviation of x
value_countscounts of cat
to_csvserialize the whole frame to a CSV string

In pandasx, the tasks are:

ts
import * as pd from 'pandasx';

const df = pd.readCsv('data.csv');
df.get(df.get('x').gt(0.5).and(df.get('cat').eq('c3')));
df.sortValues('x');
df.groupby('key').agg({ x: 'sum', y: 'mean' });
pd.merge(df, lookup, { on: 'key' });
df.assign({ z: (d) => d.get('x').mul(d.get('y')).add(d.get('n')) });
df.get('x').mean();
df.get('x').std();
df.get('cat').valueCounts();
df.toCsv();

Method ​

  • Data: a seeded synthetic table with columns id (int), key (1,000 distinct strings), cat (10 distinct strings), x, y (floats) and n (int), written to a CSV that every library reads.
  • Isolation: each library runs in its own process.
  • Timing: one warm-up run, then the median of 5 runs (3 when a run takes over 2 s, 1 over 10 s), with a garbage collection before each run.
  • Same answer: every task returns a check value (row count, number of groups, first id after sorting, mean of x), and the run fails if two libraries disagree.
  • Full work: lazy results are materialized inside the timed region: Arquero's filter / orderby with reify(), Data-Forge's pipelines with bake().
  • danfo.js readCSV only fetches URLs in Node, so read_csv does what it does internally: Papa Parse with the same options, then new DataFrame(rows).

The numbers depend on the machine; run the benchmark on yours:

bash
cd bench && npm ci
bash
npm run bench

--rows 10000,100000 changes the sizes, --runs 3 the number of runs and --tools pandasx,arquero the libraries.

Released under the MIT License.