
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
@tangent.to/ds
Advanced tools
A minimalist, browser-friendly data-science library in modern JavaScript (ESM)
A browser-friendly data science library in modern JavaScript (ESM).
npm install @tangent.to/ds
import { core, stats, ml, mva, plot } from '@tangent.to/ds';
// Linear algebra
const transposed = core.linalg.transpose([[1, 2], [3, 4]]);
// Generalized Linear Models
const model = new stats.GLM({ family: 'gaussian' });
model.fit(X, y);
const predictions = model.predict(X_new);
// K-Means clustering
const kmeans = new ml.KMeans({ k: 3 });
kmeans.fit(data);
// PCA
const pca = new mva.PCA({ center: true, scale: false });
pca.fit(data);
The GLM class unifies all regression models with a consistent interface:
// Linear regression (Gaussian family)
const lm = new stats.GLM({ family: 'gaussian' });
lm.fit(X, y);
// Logistic regression (Binomial family)
const logit = new stats.GLM({ family: 'binomial', link: 'logit' });
logit.fit(X, y);
// Multiclass classification (one-vs-rest)
const multiclass = new stats.GLM({ family: 'binomial', multiclass: 'ovr' });
multiclass.fit({ X: ['feature1', 'feature2'], y: 'species', data });
const predictions = multiclass.predict({ X: ['feature1', 'feature2'], data: newData });
// Poisson regression
const poisson = new stats.GLM({ family: 'poisson' });
poisson.fit(X, y);
// Mixed-effects model (GLMM) with random intercepts
const lmm = new stats.GLM({
family: 'gaussian',
randomEffects: { intercept: groups }
});
lmm.fit(X, y);
// Access model results
console.log(model.summary()); // Detailed summary
console.log(model.coefficients); // Coefficient estimates
const predictions = model.predict(X_new);
const model = new stats.GLM({ family: 'gaussian' });
model.fit({ formula: 'y ~ x1 + x2', data });
// Normal distribution
stats.normal.pdf(x, { mean: 0, sd: 1 });
stats.normal.cdf(x, { mean: 0, sd: 1 });
stats.normal.quantile(p, { mean: 0, sd: 1 });
// Other distributions: uniform, gamma, beta
stats.gamma.pdf(x, { shape: 1, scale: 1 });
stats.beta.pdf(x, { alpha: 1, beta: 1 });
// One-sample t-test
const result = stats.hypothesis.oneSampleTTest(data, { mu0: 0 });
// Two-sample t-test
const result = stats.hypothesis.twoSampleTTest(group1, group2);
// Chi-square test
const result = stats.hypothesis.chiSquareTest(observed, expected);
// One-way ANOVA
const result = stats.hypothesis.oneWayAnova(groups);
// Compare models with AIC/BIC
const comparison = stats.compareModels([model1, model2, model3]);
// Likelihood ratio test for nested models
const lrt = stats.likelihoodRatioTest(model1, model2);
const model = new ml.KMeans({ k: 3, maxIter: 100 });
model.fit(data);
console.log(model.labels); // Cluster assignments
console.log(model.centroids); // Cluster centers
// Classification
const knn = new ml.KNNClassifier({ k: 5 });
knn.fit(X_train, y_train);
const predictions = knn.predict(X_test);
// Regression
const knn = new ml.KNNRegressor({ k: 5 });
// Decision tree
const dt = new ml.DecisionTreeClassifier({ maxDepth: 5 });
dt.fit(X_train, y_train);
// Random forest
const rf = new ml.RandomForestClassifier({ nEstimators: 100 });
rf.fit(X_train, y_train);
const poly = new ml.PolynomialRegressor({ degree: 3 });
poly.fit(X, y);
const mlp = new ml.MLPRegressor({
layerSizes: [10, 8, 1],
activation: 'relu',
epochs: 100,
learningRate: 0.01
});
mlp.fit(X_train, y_train);
// Cross-validation
const scores = ml.validation.crossValidate(model, X, y, { cv: 5 });
// Grid search
import { GridSearchCV } from '@tangent.to/ds/ml';
const result = GridSearchCV(fitFn, scoreFn, X, y, paramGrid, { k: 5 });
const pca = new mva.PCA({ center: true, scale: false });
pca.fit(X);
console.log(pca.model.explainedVarianceRatio);
const X_transformed = pca.transform(X);
const lda = new mva.LDA();
lda.fit(X, y);
const X_transformed = lda.transform(X);
const rda = new mva.RDA();
rda.fit(response, explanatory);
const hca = new ml.HCA({ linkage: 'ward' });
hca.fit(data);
console.log(hca.model.dendrogram);
Returns Observable Plot configurations:
// ROC curve
const config = plot.plotROC(yTrue, yPred);
// Confusion matrix
const config = plot.plotConfusionMatrix(yTrue, yPred);
// PCA biplot (unified ordination plot)
const config = plot.ordiplot(pca.model, { type: 'pca', showLoadings: true, loadingFactor: 0 });
// GLM diagnostics
const config = plot.diagnosticDashboard(model);
// Classification
ml.metrics.accuracy(yTrue, yPred);
ml.metrics.f1Score(yTrue, yPred);
// Regression
ml.metrics.mse(yTrue, yPred);
ml.metrics.r2(yTrue, yPred);
npm test # Watch mode
npm run test:run # Run once
npm run test:coverage # With coverage
See docs/API.md for complete API reference.
See examples/ directory for working examples:
examples/stats/multinomial_glm_example.js - Multiclass classification demoGPL-3.0
FAQs
A minimalist, browser-friendly data-science library in modern JavaScript (ESM)
We found that @tangent.to/ds demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.