| English | 日本語 |
R-compatible statistical functions for JavaScript and the browser, written in TypeScript. Try it in the browser (every function, with the values R gives).
pt(q, df, { lowerTail: false }) is R’s pt(q, df, lower.tail = FALSE).
Results are plain objects that JSON.stringify cleanly.pnorm alone is 1.6 KB gzipped).Status: 1.3.0. The goal is to cover the numerical core of R’s
stats package (distributions, descriptive statistics, hypothesis tests, linear models, special
functions, numerical methods and the basics of linear algebra) with R-compatible results; see ROADMAP.md for what remains. See CHANGELOG.md.
npm install @numero-uno-jpn/rstats
Requires an ES2022 environment (current browsers, Node.js 22 or later, Deno, Bun).
import { pnorm, qnorm, pt, qbeta, dbinom } from "@numero-uno-jpn/rstats";
pnorm(1.96); // ≈ 0.9750021049
qnorm([0.025, 0.975]); // ≈ [-1.959963985, 1.959963985]
pt(-40, 3); // ≈ 1.719034039e-5
pt(2, 10, { lowerTail: false, logP: true }); // ≈ -3.305141551 (log of the upper tail)
qbeta(1e-10, 2, 3); // ≈ 4.082494016e-6
dbinom(3, 10, 0.2); // ≈ 0.201326592
The first argument may be a number, an array or a Float64Array; the result has the same shape.
Distribution parameters are scalars.
set.seed()import { setSeed, rnorm, RNGkind, getRandomSeed, setRandomSeed, nextRNGStream, runif } from "@numero-uno-jpn/rstats";
setSeed(42);
rnorm(3); // [1.3709584471466685, -0.5646981713960887, 0.3631284113373392]
// R: set.seed(42); rnorm(3) gives the same numbers (up to the last bit)
// R's other settings: RNGkind("L'Ecuyer-CMRG") with parallel::nextRNGStream, sample.kind = "Rounding"
RNGkind({ kind: "L'Ecuyer-CMRG" });
setSeed(1); // R: set.seed(1, kind = "L'Ecuyer-CMRG")
setRandomSeed(nextRNGStream(getRandomSeed())); // R: .Random.seed <- nextRNGStream(.Random.seed)
runif(2); // [0.31369782407981056, 0.9280126525616814]
import { tTest, fisherTest, pAdjust } from "@numero-uno-jpn/rstats";
const r = tTest([5.1, 4.9, 6.2, 5.8, 6.0, 5.5], [4.1, 4.5, 5.0, 4.8, 4.3]);
r.pValue; // ≈ 0.003536530888 (Welch, the default in R)
r.confInt; // ≈ [0.4423253335, 1.644341333]
r.method; // "Welch Two Sample t-test"
fisherTest([[3, 1], [1, 3]]).pValue; // ≈ 0.4857142857
pAdjust([0.01, 0.02, 0.03, 0.04], { method: "BH" }); // ≈ [0.04, 0.04, 0.04, 0.04]
The predictors are a matrix (array of rows) or a vector, as for lm; a binomial response can be
rows of (successes, failures).
import { glm, glmSummary, glmPredict, glmConfint, glmAnova } from "@numero-uno-jpn/rstats";
const dose = [1, 2, 3, 4, 5, 6];
const counts = [[1, 19], [4, 16], [9, 11], [13, 7], [18, 2], [19, 1]];
const fit = glm(dose, counts, { family: "binomial" }); // R: glm(cbind(s, f) ~ dose, binomial)
fit.coefficients; // ≈ [-3.77413, 1.14807]
glmSummary(fit).pValue; // ≈ [5.357e-8, 3.579e-9] (z tests)
glmPredict(fit, { newdata: [3.5], type: "response" }); // { fit: ≈ [0.56073], seFit: ≈ [0.06140] }
glmConfint(fit).lower; // ≈ [-5.27166, 0.80033] (profile likelihood)
glmAnova(fit).table[1]; // ≈ [1, 62.978, 4, 0.5196, 2.09e-15]
fit.warnings; // [] (R's warnings, such as non-convergence)
Robust covariances (sandwich’s vcovHC and vcovCL) go into lmtest’s coeftest and coefci. A modified Poisson
regression (a Poisson glm of a 0/1 outcome) gives a risk ratio with a robust interval:
import { glm, vcovHC, coefci } from "@numero-uno-jpn/rstats";
const exposed = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
const event = [1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0];
const fit = glm(exposed, event, { family: "poisson" }); // R: glm(event ~ exposed, family = poisson)
fit.coefficients.map(Math.exp); // ≈ [0.3, 2] (risk 0.3 unexposed; risk ratio 2)
const ci = coefci(fit, { vcov: vcovHC(fit, { type: "HC0" }) });
// R: lmtest::coefci(fit, vcov. = sandwich::vcovHC(fit, type = "HC0"))
ci.lower.map(Math.exp); // ≈ [0.11640, 0.68361]
ci.upper.map(Math.exp); // ≈ [0.77320, 5.8513]
lm and aov also take an R formula and a data frame (an object of columns; strings are factors). anova gives
R’s sequential table, Anova car’s type II and III tests, aovEz afex’s repeated-measures ANOVA with the
Greenhouse-Geisser correction and generalized eta squared.
import { lm, anova, Anova, aovEz } from "@numero-uno-jpn/rstats";
const d = { y: [12.1, 14.3, 13.8, 17.2, 19.5, 22.4, 11.6, 13.9, 15.7, 18.8, 21.1, 25.3],
A: ["a", "a", "b", "b", "c", "c", "a", "a", "b", "b", "c", "c"],
B: ["p", "q", "p", "q", "p", "q", "p", "q", "p", "q", "p", "q"] };
const fit = lm("y ~ A * B", d, { contrasts: { A: "contr.sum", B: "contr.sum" } });
anova(fit).rowNames; // ["A", "B", "A:B", "Residuals"]
anova(fit).table[0]; // ≈ [2, 169.147, 84.573, 57.828, 0.00011997] (Df, Sum Sq, Mean Sq, F, p)
Anova(fit, { type: 3 }).table[1]; // ≈ [169.147, 2, 57.828, 0.00011997] (car::Anova(fit, type = 3))
// repeated measures (R: afex::aov_ez("id", "y", long, within = "W"))
const long = { id: ["s1", "s1", "s1", "s2", "s2", "s2", "s3", "s3", "s3", "s4", "s4", "s4", "s5", "s5", "s5"],
W: ["pre", "mid", "post", "pre", "mid", "post", "pre", "mid", "post", "pre", "mid", "post", "pre", "mid", "post"],
y: [5.1, 6.3, 7.2, 4.8, 5.9, 7.5, 6.0, 6.1, 8.3, 5.5, 6.8, 7.1, 4.9, 6.6, 7.8] };
aovEz(long, { id: "id", dv: "y", within: "W" }).anova.table[0];
// ≈ [1.735, 6.940, 0.21653, 35.876, 0.84607, 0.00026363] (num Df, den Df, MSE, F, ges, p; GG-corrected)
lmer fits lme4’s linear mixed models by REML or maximum likelihood. It is in its own area,
@numero-uno-jpn/rstats/mixed (dist/mixed.js on a CDN), not in the single-file bundle.
import { lmer, lmerSummary, lmerAnova } from "@numero-uno-jpn/rstats/mixed";
const d = { subj: ["s1", "s2", "s3", "s4", "s5", "s6"].flatMap((s) => [s, s, s, s]),
day: [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3],
rt: [251, 262, 280, 293, 230, 251, 265, 282, 270, 275, 290, 318,
242, 263, 270, 296, 260, 284, 309, 330, 238, 245, 262, 268] };
const fit = lmer("rt ~ day + (day | subj)", d); // R: lme4::lmer(rt ~ day + (day | subj), d)
fit.fixef; // [247.65, 16.4]
fit.coefTable.stdError; // ≈ [5.3177, 1.7104]
fit.varCorr[0].sd; // ≈ [12.485, 3.6894] (subj: intercept and slope; VarCorr)
fit.varCorr[0].corr[0][1]; // ≈ 0.6737
fit.sigma; // ≈ 4.4385
fit.ranef[0].values[1]; // ≈ [-13.118, -1.0038] (ranef for s2)
fit.REMLcrit; // ≈ 158.563
// lmerTest's tests, with Satterthwaite's degrees of freedom
const s = lmerSummary(fit); // R: summary(lmerTest::lmer(rt ~ day + (day | subj), d))
s.df; // ≈ [5, 5]
s.pValue; // ≈ [8.6215e-8, 0.00020903]
lmerAnova(fit).F; // ≈ [91.942] (Type III; R: anova(fit))
The estimates are the exact optimum of the REML criterion; lme4’s optimiser stops close to it, so the variance
components agree with lme4 to about 5 to 9 significant digits and the fixed effects and log-likelihood to more.
lmerSummary, lmerContest and lmerAnova give lmerTest’s t- and F-tests with Satterthwaite’s degrees of freedom
(computed with exact derivatives at that optimum; lmerTest differentiates numerically at lme4’s) and the Type I,
II and III ANOVA tables; lmerAnova([fit1, fit2]) compares fits by likelihood-ratio tests, as lme4’s anova().
glmer fits lme4’s generalized linear mixed models (binomial, poisson, Gamma, inverse.gaussian and gaussian families
with their links) by the Laplace approximation, or by adaptive Gauss-Hermite quadrature (nAGQ 2 to 100) for a
single scalar random-effects term: glmer("y ~ x + (1 | g)", d, { family: "poisson" }). glmerSummary gives the
coefficient table with p-values, glmerAnova the ANOVA table or the likelihood-ratio comparison of glmer, lmer and
glm fits, and glmerPredict and lmerPredict the predictions (at new data, with some or none of the random
effects, with standard errors). As for lmer, the estimates are the exact optimum; see the
differences for the standard errors and nAGQ > 1.
import { cohensD, etaSquared, Anova, powerTTest, pwrAnovaTest } from "@numero-uno-jpn/rstats";
cohensD([5.1, 4.9, 6.2, 5.8, 6.0, 5.5], [4.1, 4.5, 5.0, 4.8, 4.3]);
// ≈ { name: "Cohens_d", value: 2.30726, ci: 0.95, ciLow: 0.68824, ciHigh: 3.85666 } (effectsize::cohens_d)
etaSquared(Anova(fit, { type: 3 })).table[0]; // ≈ [0.95068, 0.95, 0.82023, 1] (fit from the example above; partial eta², one-sided CI)
powerTTest({ delta: 0.5, power: 0.8 }).n; // ≈ 63.766 per group (power.t.test)
pwrAnovaTest({ k: 3, f: 0.25, power: 0.8 }).n; // ≈ 52.397 (pwr::pwr.anova.test)
The confidence limits are the exact solutions; effectsize finds them with an optimiser and is up to about 1e-9 (sometimes 3e-3) off.
Matrices are arrays of rows.
import { solve, qr, qrCoef, svd, eigen } from "@numero-uno-jpn/rstats";
solve([[2, 1], [1, 3]]); // [[0.6, -0.2], [-0.2, 0.4]]
const q = qr([[1, 1], [1, 2], [1, 3]]);
qrCoef(q, [1, 3, 4]); // ≈ [-0.333, 1.5] (least squares)
svd([[1, 4], [2, 5], [3, 6]]).d; // ≈ [9.508032001, 0.7728696357]
eigen([[2, 1], [1, 3]]).values; // ≈ [3.618033989, 1.381966011]
| Area | Functions (R names in parentheses where they differ) |
|---|---|
| Special functions | gamma, lgamma, beta, lbeta, choose, lchoose, factorial, lfactorial, digamma, trigamma, psigamma, besselI, besselK, besselJ, besselY; also erf, erfc, erfinv, erfcinv, gammainc and perm, which R lacks, and log1pmx, lgamma1p, log1mexp, log1pexp from R’s C API (Rmath.h) |
| Distributions (d/p/q) | normal, t, chi-squared, F, beta, gamma, binomial, Poisson, uniform, exponential, log-normal, logistic, Cauchy, Weibull, geometric, negative binomial, hypergeometric, Wilcoxon signed rank and rank sum, studentized range (ptukey, qtukey), non-central chi-squared, t, F and beta (ncp); the multinomial probability (dmultinom); inverse gamma, Kumaraswamy, Pareto, triangular, Laplace (extraDistr) and arcsine; distSummary (mean, variance, sd, median, mode, skewness, kurtosis) |
| Random numbers | setSeed (set.seed), RNGkind (Mersenne-Twister and L’Ecuyer-CMRG, sample.kind Rejection and Rounding), getRandomSeed/setRandomSeed (.Random.seed), nextRNGStream/nextRNGSubStream (parallel), 26 r* functions, sample, sampleInt (sample.int), r2dtable |
| Descriptive statistics | sum, prod, mean, weightedMean (weighted.mean), variance (var), sd, median, range, cumsum, cumprod, cummax, cummin, diff, quantile, IQR, fivenum, mad, rank, cov, cor, tabulate, table, unique, cut, findInterval, pretty, hist, ecdf, scale, skewness, kurtosis, geometricMean, modes, meanAD, cv |
| Hypothesis tests | tTest, chisqTest, fisherTest, wilcoxTest, corTest, binomTest, poissonTest, propTest, mcnemarTest, varTest, bartlettTest, kruskalTest, friedmanTest, quadeTest, flignerTest, moodTest, onewayTest, shapiroTest, mantelhaenTest, ansariTest, ksTest, pairwiseTTest, pairwiseWilcoxTest, pairwisePropTest, aov (one way, a fit whose table is aovSummary), TukeyHSD, zTest, brunnerMunzelTest, pAdjust (p.adjust) |
| Analysis of variance | aov and aovSummary with a formula (several factors, interactions, covariates, Error() strata), anova (anova.lm, sequential and model comparison), Anova (car: types II and III), aovEz (afex: repeated-measures and mixed designs, Greenhouse-Geisser and Huynh-Feldt corrections, generalized and partial eta squared), mauchlyTest (mauchly.test) |
| Effect sizes and power | cohensD, hedgesG (effectsize, with exact confidence limits), etaSquared, omegaSquared, epsilonSquared (partial, generalized, from anova and Anova tables); powerTTest, powerPropTest, powerAnovaTest (power.*.test); pwrTTest, pwrT2nTest, pwr2pTest, pwr2p2nTest, pwrPTest, pwrNormTest, pwrRTest, pwrChisqTest, pwrAnovaTest, pwrF2Test, esH, esW1, esW2, cohenES (pwr) |
| Linear models | lm (a formula and a data frame, or a matrix, with the summary quantities), modelMatrix (model.matrix), confint, predict; glm (matrix interface, every family and link of R’s stats) with glmSummary (summary.glm), glmResiduals (the four kinds), glmHatvalues, glmRstandard, glmCooksDistance, glmPredict (with standard errors), glmConfint (profile likelihood, exact limits), glmAnova (anova.glm); vcovHC, vcovCL (sandwich: HC0 to HC5, one-way and multi-way clustered), coeftest, coefci (lmtest) |
| Mixed models | lmer (lme4: REML and ML, correlated and uncorrelated random effects, crossed and nested grouping factors; fixef, vcov, VarCorr, ranef, logLik, AIC, BIC, REMLcrit, isSingular), lmerSummary, lmerContest and lmerAnova (lmerTest: Satterthwaite’s t- and F-tests, Type I/II/III ANOVA tables; likelihood-ratio comparison of fits), glmer (lme4: all glm families, Laplace approximation and adaptive Gauss-Hermite quadrature), glmerSummary, glmerAnova, glmerPredict and lmerPredict, from @numero-uno-jpn/rstats/mixed |
| More tests | leveneTest, propTrendTest (prop.trend.test), jonckheereTest, cochranQTest, adTest, lillieTest, cvmTest, sfTest, pearsonTest (car, DescTools, clinfun, nortest); tTOST, tsumTOST (TOSTER: equivalence and minimal-effect t tests) |
| Contingency tables and proportions | binomCI, binomDiffCI, binomRatioCI (DescTools’ BinomCI, BinomDiffCI, BinomRatioCI), oddsRatio (epitools, and epiR’s score interval), fisherTest(x, { midp: true }) (exact2x2), boschlooTest (Exact), gTest, stuartMaxwellTest, goodmanKruskalGamma (DescTools), lblTest (coin), chisqTest(x, { nMinus1: true }) (Campbell’s ‘N − 1’ test) and Freeman-Tukey residuals, tost (equivalence), binomDiffEquivalenceTest (score TOST of two proportions) |
| Multiple comparisons | dscfAllPairsTest (Steel-Dwass), kwAllPairsDunnTest, kwManyOneDunnTest, manyOneUTest (Steel’s many-one rank test), dunnettTest, gamesHowellTest, tukeyTest (PMCMRplus), dunnTest (dunn.test), glhtDunnett (multcomp) |
| Survival analysis | survdiff (log-rank), survfit (Kaplan-Meier with intervals and median), coxph (Cox regression: Efron and Breslow ties, case weights, strata, the Wald, likelihood-ratio and score tests, the robust variance and cluster) |
| Diagnostic accuracy and method comparison | roc, auc, ciAuc (ci.auc), rocTest (roc.test), coords (pROC: DeLong’s interval and test, the bootstrap, partial AUC), diagnosticTests (epiR’s epi.tests), blandAltman (BlandAltmanLeh’s bland.altman.stats), mcreg (mcr: Deming, weighted Deming and Passing-Bablok regression) |
| Agreement and reliability | kappa2, kappamFleiss, icc (irr), ICC (psych: the six forms of Shrout and Fleiss), cronbachAlpha, partialR (psych), polychor, polyserial (polycor), pbvnorm, factanal, omega (McDonald’s ω, psych) |
| Data handling | completeCases (complete.cases), naOmit (na.omit), subset, merge, rbind and cbind of data frames, tapply, split, aggregate, pivotLonger and pivotWider (tidyr), fromRows and toRows (a data frame from an array of row objects and back); formula forms of the tests (tTest("y ~ g", data), kruskalTest, friedmanTest("y ~ w \| b", data), corTest("~ x + y", data), …) |
| Linear algebra | matMul (%*%), add, subtract, multiply, divide, outer, t, diag, cbind, rbind, matrix, kronecker, seq, crossprod, tcrossprod, norm, backsolve, forwardsolve, chol, chol2inv, qr with qrQ, qrR, qrX, qrCoef, qrQy, qrQty, qrResid, qrFitted, qrSolve (qr.Q …), solve, det, determinant, rcond, kappa, svd, eigen, lu, prcomp, ginv (MASS), schur, expm |
| Numerical methods | integrate, optimize, optim, optimHess, uniroot, approx, spline, splinefun, splinefunH, barylag, hermiteInterp, ode, grad, jacobian, hessian |
New to R’s way of writing an analysis (data frames, formulas, factors)? docs/guide-for-js-developers.md explains it from a JavaScript developer’s point of view, with a worked example.
Coming from jStat? docs/migrating-from-jstat.md lists the replacement for every jStat function.
The API reference documents every function, with an example
for each (the examples are run by the tests). docs/r-functions.md lists the R function that
each one corresponds to. (npm run docs builds the reference locally.)
For AI coding assistants, llms.txt summarises how R code translates to rStats.js calls (also in the npm package and at https://numero-uno-jpn.github.io/rStats.js/llms.txt).
Expected values are produced by R scripts in oracle/ and stored in
test/fixtures/, so the test suite runs without R. A case passes if it matches
R, or if R is wrong there and rStats.js matches a high-precision value computed with Rmpfr or
gmp. In the far tails and for large parameters rStats.js is often more accurate than R, because
it computes exponents in double-double arithmetic. Details: docs/accuracy.md.
Most differences are cases where R loses accuracy or fails. The deliberate ones that affect everyday use:
sampleInt(n) returns 0..n-1 (R’s sample.int() minus 1, from the
same random stream), and pivots of qr and chol are 0-based.warnings: R’s text, each distinct warning once, [] when there are none). To print
them as R does, set a handler, which receives each warning of a call once with the name of the function called:
setWarningHandler((message, source) => console.warn(source + ": " + message)). A handler that throws plays the
part of R’s options(warn = 2), and setWarningHandler(null) stops it.mcnemarTest on a table without discordant pairs, or lu of a matrix with NaN). The distribution
functions (d/p/q/r) return NaN for invalid parameters, as R. See
the general differences.exact: false. R computes most of these however long they
take. See Limits.lmer and glmer return the exact optimum of their criterion, which lme4’s optimiser approaches only to its
tolerances, and do not emit lme4’s convergence warnings. For nAGQ > 1, glmer’s log-likelihood is the true one
(lme4 leaves out a constant).Full list: docs/differences-from-r.md.
With a bundler (Vite, esbuild, webpack, Rollup), import named functions; unused functions are removed. Approximate sizes after minification and gzip:
| Import | gzip |
|---|---|
pnorm |
1.6 KB |
setSeed, rnorm |
2.0 KB |
solve / svd / eigen |
2.4 / 2.4 / 5.1 KB |
wilcoxTest / fisherTest / tTest |
18.9 / 27.9 / 31.0 KB |
qbeta / pt and qt |
43.9 / 40.4 KB |
glm and glmSummary / glm with all its methods |
35.0 / 51.4 KB |
lmer (from /mixed) / with lmerSummary, lmerContest, lmerAnova |
19.4 / 70.0 KB |
glmer (from /mixed) / with glmerSummary, glmerAnova, glmerPredict |
47.2 / 66.1 KB |
everything (except /mixed) |
289.5 KB |
(npm run size measures these.)
Each area is also a subpath export, for importing one area without the rest:
@numero-uno-jpn/rstats/distributions, /tests (hypothesis tests, lm, confint and
predict, and glm with its methods), /linalg, /descriptive, /numerics, /special and /mixed
(lmer, glmer and their methods; this area is only available this way, not from the main entry point).
Without a bundler, load the single-file build dist/rstats.js (one minified ES module with every
function except those of /mixed, 290 KB gzipped) from jsDelivr, which serves each npm release:
<script type="module">
import { pnorm } from "https://cdn.jsdelivr.net/npm/@numero-uno-jpn/rstats@1.3.0/dist/rstats.js";
console.log(pnorm(1.96)); // ≈ 0.9750021049
</script>
The functions are named exports with R’s names, without a prefix such as jStat. or _.. To
keep them apart from other names, import the module as a namespace (import * as rs from the
URL above) and call rs.pnorm(1.96), rs.tTest(x, y). With a bundler, unused functions are
still removed (import * as rs from "@numero-uno-jpn/rstats"); from a CDN the whole file is
loaded either way. Nothing is added to window: to use the functions from other scripts or the
browser console, assign window.rs = rs yourself.
A page that needs only some areas can load the per-area bundles instead: dist/distributions.js,
dist/tests.js, dist/linalg.js, dist/descriptive.js, dist/numerics.js, dist/special.js and
dist/mixed.js export the same functions as the subpaths above, and share their common code through
dist/chunks/, so loading two areas does not load that code twice. With its chunks, one area
transfers 39 KB (special) to 250 KB (tests) gzipped.
Use either dist/rstats.js or the per-area bundles on one page, not both: they are separate sets of modules, so a
page that mixes them loads the common code twice and has two random number states (setSeed from one does not seed
the generators of the other). The same holds for dist/rstats.js with dist/mixed.js, which brings its own copy
of the common code.
Other npm-based CDNs work as well, for example https://esm.sh/@numero-uno-jpn/rstats. Release tags also contain
the build output (dist/), which is not on the main branch, but jsDelivr’s GitHub route
(cdn.jsdelivr.net/gh/...) does not serve tags from 0.12.0 on: with the test fixtures, the repository exceeds its
size limit of 50 MB. Use the npm route above.
The browser build is tested in headless Chromium, both bundled and as dist/rstats.js loaded as
an ES module (npm run test:browser).
Demo: https://numero-uno-jpn.github.io/rStats.js/demo/. demo/ is a static page that loads dist/rstats.js from jsDelivr and exercises
every function: distributions with plots, special functions, random numbers, hypothesis tests and
linear algebra. Each form shows the equivalent R and JavaScript code for its inputs, and a “Compare
with R” tab checks curated examples against values printed by R (source("examples.R") runs them
all in R). To use your own build instead of the CDN, run npm run build, serve the repository root
with a static server (for example npx serve .) and open /demo/?src=local.
While the version is 0.x, a minor release may contain breaking changes; they are listed in the changelog.
From 1.0.0, rStats.js follows Semantic Versioning. The public API is what the package root and its subpaths export, with the documented names, arguments, options, result fields and their types.
TypeError, RangeError, SyntaxError, Error); a tighter computation limit; dropping a Node.js version that
is still supported.warnings and messages, non-enumerable
or undocumented fields, and files under dist/ other than the entry points and the dist/*.js bundles. Where a
new version of R changes its own values or random streams, rStats.js follows it in a minor version.optim’s control), so a misspelt option cannot be ignored without a sign. A new option is therefore a minor
change: the key it adds was an error before.See CONTRIBUTING.md for how the comparison with R works and the licensing rules (no code from R or GPL packages). Notes on speed and the double-double arithmetic are in docs/performance.md.
MIT. Numerical kernels are ported from SciPy’s xsf, scipy.stats and C translation of QUADPACK (BSD-3), Boost.Math (BSL-1.0), statsmodels (BSD-3) and the LAPACK reference implementation (modified BSD), plus public-domain LINPACK, EISPACK, Cephes, QUADPACK and netlib code. See THIRD_PARTY_NOTICES.md.