Characterizing several JavaScript polynomial-regression implementations against a
NumPy gold standard, so you can trade off
numerical
stability,
speed, and
code simplicity for your
context. Start with the recommendation below; expand the methodology when you want to
audit how the evidence was produced.
For a dedicated
speed study, see the
fit-speed grid — how the two fastest scaled methods
(
simple (scaled) and
forsythe) slow down as the data grows
from 8 to 1 million points, across polynomial degrees 1–6 and three data shapes, in
all three major JavaScript engines (V8, JavaScriptCore, SpiderMonkey).
Methodology, definitions, and important timing caveats
No JS library does the fully robust thing (center and scale, or a QR/SVD
solve), and the popular ones fail differently:
ml.js solves a
raw Vandermonde with normal equations — no centering, no scaling — so it
loses accuracy for shifted or large x.
d3-regression
mean-centers x for degree ≥ 2 (so it tolerates large offsets there) but
never scales, so it still degrades on wide-range x and high degree — and
its degree-1 path doesn't center at all, so even a straight-line fit on offset x
(epoch-ms timestamps ≈ 1.7e12) loses accuracy.
Accuracy = each implementation's in-range predictions vs NumPy
(numpy.polynomial.Polynomial.fit, computed offline into
numpy-reference.js), relative to the response range.
Cell colour: <1e‑6
<1e‑3
worse. R² is the fit quality.
Speed = each implementation timed relative to the
fastest correct method on that case (which reads 1.00×) — so a bigger
number means slower. Every method within 10% of it is marked ⚡ and counts as tied for
fastest, since the exact winner among methods that close is just measurement noise.
Timing note: a d3-regression fit also returns an adaptively-sampled polyline for
drawing the curve, which for degree ≥ 2 can cost far more than the fit itself —
most of all on well-scaled x, where its angle-based subdivision goes deepest. This page
only uses predict and the coefficients, so both d3 rows pass
.domain([0,0]) to skip that sampling; coefficients and predictions are
unchanged by it.
Each card plots the data with every implementation's fitted curve overlaid (coloured as in
the legend below); the y-axis is clamped to the data range, so on ill-conditioned cases the
unstable fits visibly shoot off the frame. The picker below recommends an implementation
live from these measured runs.