Pick a test, enter your numbers, and get the statistic, p-value, and the assumption check that tells you which result to trust.
Concept, Direction & Testing: Dr G Narenthiran FRCS(SN)
Step 1
| Total | |||
|---|---|---|---|
| 100 | |||
| 100 | |||
| Total | 45 | 155 | 200 |
Chi-squared test
Fisher's exact test
Effect size
Step 1
Step 2
Columns that parse cleanly as numbers default to Continuous; everything else defaults to Nominal. Override any of these — for example, a numeric-coded stage or grade is usually Ordinal, not Continuous. Mark identifiers, chart numbers, or free-text notes as Meta / ID to keep them out of the summary and pivot builder below.
| Column | Type | Summary |
|---|
Step 3
Step 4
Association test
Expected counts — for each cell, Eᵢⱼ = (row total × column total) ⁄ grand total — the count that would be expected if the row and column variables were independent.
Test selection (Cochran's criteria) — if any expected count is below 1, or more than 20% of cells have an expected count below 5, the chi-squared approximation is considered unreliable, and an exact test is used instead: Fisher's exact test for a 2×2 table, or the Fisher–Freeman–Halton exact test (the same idea generalized to any number of rows/columns) for larger tables. Otherwise, Pearson's chi-squared test of independence is used, with Yates' continuity correction also shown for 2×2 tables.
Fisher–Freeman–Halton — enumerates every possible table with the same row and column totals as the one observed, computes the exact hypergeometric probability of each, and sums the probabilities of every table at least as improbable as the one observed — the exact multi-category generalization of Fisher's exact test, needing no large-sample assumption. This is validated in this app by confirming it reproduces the 2×2 Fisher's exact result exactly on 2×2 tables. Enumeration is only feasible for reasonably small tables — if a table is too large to enumerate in the browser, this tool falls back to the chi-squared approximation and says so explicitly, rather than silently reporting an unreliable number as if it were exact.
Cramér's V — √(χ²⁄(N×min(r−1,c−1))), an effect size between 0 (no association) and 1 (perfect association) that, unlike the p-value, doesn't shrink automatically as the sample size grows.
Odds ratio / relative risk (2×2 only) — computed the same way as the Contingency table tab, with a 0.5 continuity correction applied to all four cells when any cell is zero, and 95% Wald confidence intervals on the log scale.
Category filtering — unchecking a category removes every row containing that value from the cross-tabulation and the test — it does not merge it into the other categories. Excluding categories changes the effective sample size and margins, so the test re-runs on exactly the filtered data shown in the table above it.
Not implemented — Monte Carlo approximation for large tables that exceed the exact-enumeration limit (the tool falls back to the ordinary chi-squared approximation instead), and multi-way (three or more variable) pivot tables.
Step 1
One value per line, or comma-separated — you can paste directly from a spreadsheet column.
One value per line, or comma-separated — you can paste directly from a spreadsheet column.
Step 2
Why Shapiro–Wilk — of the common normality tests (Kolmogorov–Smirnov, Lilliefors, Anderson–Darling, D'Agostino–Pearson), comparative power studies (Razali & Wah, 2011) consistently find Shapiro–Wilk the most powerful at detecting non-normality across most alternative distributions — especially at the small-to-moderate sample sizes typical here. p-values use Royston's (1995) approximation, valid for 3–5000 observations. A significant result (p < 0.05) is evidence against normality — reason to consider a non-parametric alternative (Mann–Whitney U for independent samples, Wilcoxon signed-rank for paired) instead of the t-test. With very small samples the test also has limited power, so a non-significant result here isn't strong proof of normality either — it mainly means no departure was detected.
Visual check
Each histogram picks its own bin width from its data via the Freedman–Diaconis rule (2·IQR⁄∛n) — wider spread gives wider bins, and it's robust to outliers since it's based on the interquartile range rather than the min/max. The two histograms aren't on a shared scale, so compare shape, not bar-to-bar height. This is the visual complement to the Shapiro–Wilk check above.
Step 3
Why Levene's test — it tests equality of variance using deviations from each group's median rather than its mean (the Brown–Forsythe form), which keeps it reliable even when a group isn't perfectly normal — unlike the plain F-test, which assumes normality itself. A significant result (p < 0.05) means the two groups' spreads differ enough that pooling them (Student's t-test) would understate or overstate the standard error — use Welch's t-test instead.
Descriptives
| Statistic | Group A | Group B |
|---|
Test result
Visual check
Effect size
Step 1
One value per line, or comma-separated — you can paste directly from a spreadsheet column.
One value per line, or comma-separated — you can paste directly from a spreadsheet column. Matched by position with X.
Visual check
Step 2
Why Shapiro–Wilk — Pearson's r assumes both variables are approximately normally distributed; Shapiro–Wilk is the most powerful common test for flagging when that assumption doesn't hold (Razali & Wah, 2011), which is why it's used here to help decide between Pearson's r and Spearman's rank correlation.
Step 3
Why this test — Pearson's r and linear regression both assume the relationship is a straight line, not merely monotonic. This is a curvature test: it fits a quadratic term (y = b₀+b₁x+b₂x²) alongside the linear one and checks, via an F-test, whether that curvature term explains significantly more variance than the line alone. A significant result (p < 0.05) is evidence the relationship bends — reason to prefer Spearman's rank correlation over Pearson's r, and to treat a linear regression fit with caution. It complements, but doesn't replace, looking at the scatter plot above.
Correlation
Step 4
Why these tests — linear regression's significance tests additionally assume the residuals (actual − predicted) are normally distributed and have constant variance across X (homoscedasticity). Residual normality is checked with Shapiro–Wilk again, this time on the residuals. Constant variance is checked with a single-predictor Breusch–Pagan diagnostic: it regresses the squared residuals on X and tests whether that explains a significant share of their variance (via n·R², a chi-squared statistic with 1 df) — a significant result (p < 0.05) means the spread of residuals changes across X, so standard errors on the slope may be misleading.
Linear regression
Step 1
Step 2
First row is the header. Comma, tab, or space separated. Paste your own data or use the columns below to tell us which column is which.
Data quality
Kaplan–Meier plot
One-group results
Two-group results
| Group | N | Events | Censored | % censored | Median survival | 95% CI |
|---|
Log-rank test
Transparency
Export
Downloads ask for confirmation before saving anywhere this page runs. Clipboard copy may be blocked in some embedded previews — if "Copy" doesn't seem to work, select the text and copy it manually.
What it is — Kaplan–Meier estimation tracks the probability of "surviving" (not yet having the event) over time in a group that includes some incomplete observations. It's the standard way to summarize time-to-event data — death, relapse, device failure, discharge — when not everyone has been followed for the same length of time or reached the event by the end of the study.
Event vs. censoring — An event (coded 1) is the outcome you're tracking actually happening. A censored observation (coded 0) is someone who left the risk set without the event happening — the study ended, they were lost to follow-up, or they withdrew. Censoring is not a negative result and is not the same as loss to follow-up in general — it specifically means "we know they hadn't had the event as of this time, but we don't know what happened after."
The formula — Ŝ(t) = Πtᵢ≤t (1 − dᵢ⁄nᵢ), where nᵢ is the number still at risk just before time tᵢ and dᵢ is the number of events at tᵢ. The curve only steps down at event times; a censoring removes someone from the risk set for later times but doesn't itself drop the curve.
Median survival — the earliest time at which the estimated survival probability falls to 0.50 or below — i.e., the point by which half the cohort has had the event. If the curve never reaches 0.50 during follow-up, the median is genuinely not known yet; reporting the last observed time as if it were the median would be wrong, so this app says "not reached" instead.
Confidence intervals — computed with Greenwood's formula for the variance of Ŝ(t), combined with a complementary log-log transformation before building the interval and transforming back. This keeps every confidence bound inside [0, 1] and is generally more accurate than a plain linear interval, especially near the ends of the curve.
The log-rank test — compares two Kaplan–Meier curves by summing, at every time an event occurs in either group, the difference between observed and expected events in one group (expected under the null hypothesis that both groups share the same survival function), weighting by the hypergeometric variance at each time. It tests whether the two survival distributions differ over the whole observed follow-up — it does not estimate the size of the difference (that's what a hazard ratio from a Cox model is for), and it can be underpowered if the two curves cross, or if either group has few events.
Statistical vs. clinical significance — a small p-value only says the observed difference is unlikely under the null hypothesis given this sample; it says nothing about whether the difference is large enough to matter clinically, and a non-significant result with a small sample doesn't prove the groups are equivalent. Curves, medians and p-values here should be read alongside the actual sizes of the effects and confidence intervals, not the p-value alone.
Not yet implemented
A hazard ratio should come from a Cox model, not be read off Kaplan–Meier curves or computed from median survival times — both would misrepresent the comparison. That model isn't implemented in this tool yet, so no hazard ratio is shown here. Use the log-rank test above for whether the curves differ, and treat any hazard ratio you compute elsewhere as a separate analysis from this one.
Step 1
One value per line, or comma-separated — you can paste directly from a spreadsheet column. At least 2 groups, at least 2 values each (3+ recommended for the normality check).
Visual check
Bars show each group's mean; error bars show the 95% CI of the mean (t-distribution, df = n−1).
Visual check
Each histogram picks its own bin width via the Freedman–Diaconis rule — the panels aren't on a shared scale, so compare shape, not bar-to-bar height.
Step 2
Why Shapiro–Wilk — standard ANOVA assumes each group is approximately normally distributed; Shapiro–Wilk is the most powerful common test for flagging when that assumption doesn't hold (Razali & Wah, 2011). If any group departs from normality, this tool looks for a transformation before falling back to the fully non-parametric Kruskal–Wallis test.
Step 3
Why Levene's test — generalized to k groups as a one-way ANOVA on each group's deviations from its own median (the Brown–Forsythe form), which stays reliable even when a group isn't perfectly normal. A significant result (p < 0.05) means the groups' spreads differ enough that standard ANOVA's equal-variance assumption doesn't hold — use Welch's ANOVA instead.
Step 4
Why this step — when a group departs from normality, a Box–Cox power transform (y = (xλ−1)⁄λ, or ln(x) at λ = 0) is searched over a grid of λ from −2 to 2, picking whichever value maximizes the transform's profile log-likelihood for this data. If the transformed groups are then consistent with normality, Welch's ANOVA runs on the transformed values — Welch's rather than standard ANOVA, since the transform isn't guaranteed to equalize variances too. If no transform fixes normality, this tool falls back to the fully non-parametric Kruskal–Wallis test instead of trusting a transform that didn't work. Box–Cox needs strictly positive data — if any value is zero or negative, a constant is added to every value first, shown below.
Test result
| Source | SS | df | MS | F | p |
|---|
Not yet implemented
A significant omnibus result here says at least one group differs — it doesn't say which pair. Proper follow-up (Tukey's HSD, Games–Howell for unequal variances, or Dunn's test after Kruskal–Wallis, each with a multiple-comparisons correction) isn't implemented in this tool yet, so no pairwise p-values are shown. Treat any pairwise comparison you make by eye on the chart above as exploratory, not confirmatory.
Step 1
Step 2
One continuous value per line, or comma-separated.
One group label per line, or comma-separated — matched by position with the outcome above. At least 2 distinct groups.
Step 3
Continuous covariate(s) to adjust for, one value per line matched by position with the outcome and group above. At least one covariate.
Visual check
Bars show each group's mean after adjusting for the covariate(s) (holding them at their overall average) — not the raw group means; error bars show the 95% CI.
Step 4
Why this matters — ANCOVA assumes the covariate's relationship with the outcome is the same slope in every group — if the groups' slopes genuinely differ, a single "adjusted" comparison at the covariate's average value can be misleading at other values of the covariate. This is tested by adding a group × covariate interaction term and checking whether it significantly improves the fit.
Test result
| Source | SS | df | MS | F | p |
|---|
Adjusted means
| Group | Adjusted mean | SE | 95% CI |
|---|
Coefficients (full model)
| Term | Estimate | SE | t | p |
|---|
Step 2
One group label per line, or comma-separated. At least 2 distinct groups.
Step 3
Continuous dependent variables, one value per line matched by position with the group above. At least 2 dependent variables.
Test result
| Wilks' Λ | F | df1 | df2 | p |
|---|
Follow-up
| Dependent variable | F | df | p | η² |
|---|
Follow-up univariate tests are only meaningful after a significant multivariate result above, and don't themselves correct for running one test per dependent variable (consider a Bonferroni correction — divide 0.05 by the number of dependent variables — if treating each as a separate confirmatory test).
Step 1
Step 2
0 = event did not occur, 1 = event occurred. Matched by position with each predictor below.
Step 3
For each predictor, choose its measurement type — this changes how it enters the model. Continuous — used as-is (e.g. age, dose). Ordinal — categories with a natural order but no assumed equal spacing (e.g. stage I/II/III); entered as an equally-spaced numeric score in that order, which assumes a linear effect across categories. Nominal — unordered categories (e.g. treatment arm); automatically dummy-coded against a reference category, so each non-reference level gets its own coefficient.
Visual check
Step 4
Test result
| Term | Estimate | SE | z | p | OR | 95% CI |
|---|
Classification at p = 0.50
| Predicted 0 | Predicted 1 | |
|---|---|---|
| Actual 0 | — | — |
| Actual 1 | — | — |
A simple threshold summary, not a substitute for the coefficient test above — accuracy alone can look good on an imbalanced outcome even when the model adds little.
Fitting — both models are fit by Newton–Raphson (equivalent to iteratively reweighted least squares) maximizing the exact log-likelihood over all predictors at once — logistic: Σ[yᵢlog(pᵢ)+(1−yᵢ)log(1−pᵢ)] with pᵢ = 1⁄(1+e−ηᵢ); Poisson: Σ[yᵢlog(μᵢ)−μᵢ−log(yᵢ!)] with μᵢ = eηᵢ, where ηᵢ = β₀ + β₁x₁ᵢ + β₂x₂ᵢ + … is the linear predictor. Standard errors come from the observed information matrix (inverse Hessian) at convergence.
How predictor type changes the model — a continuous predictor contributes its raw value as one column of the design matrix, with one coefficient. An ordinal predictor is converted to an equally-spaced numeric score following its category order (typed order, or auto-detected: numeric sort if the categories are already numbers, otherwise the order they first appear) and enters as one column with one coefficient — this assumes the effect of moving up one category is the same size at every step, which is a simplification worth checking against subject-matter knowledge. A nominal predictor with k categories is dummy-coded into k−1 binary columns against a reference category (the first category encountered in the data), so each non-reference level gets its own coefficient, estimated without assuming any order or equal spacing between categories.
Odds ratio / incidence rate ratio / relative risk — for each term, eβ — the multiplicative change in odds (logistic), rate (Poisson), or risk (relative risk regression for binary outcomes) per one-unit increase (continuous or ordinal) or per category vs. the reference (nominal) — with a 95% Wald CI from eβ ± 1.96·SE(β). Wald intervals are the conventional choice but are known to be less reliable with sparse data, very large coefficients, or near-separation — the events-per-variable and convergence checks below are the main safeguards against relying on one in exactly those conditions.
Relative risk regression for binary outcomes — logistic regression's odds ratio overstates the relative risk whenever the outcome is common (roughly above 10%), which matters if what you actually want is "how many times more likely," not "how much greater the odds." This option gets a relative risk directly (eβ) by trying two models, in order. First, log-binomial regression — a binomial-family model with a log link — is fit; this is the statistically correct likelihood for a 0/1 outcome, so its standard errors need no further correction, but log(p) must stay below 0 for the likelihood to be defined at all, which is why log-binomial models are well known to sometimes fail to converge (an unconstrained step can overshoot that boundary). When that happens, this tool automatically falls back to fitting the same Poisson log-link model to the 0/1 outcome instead ("modified Poisson regression," Zou 2004); because a 0/1 outcome doesn't really follow a Poisson distribution (its true variance is p(1−p), not equal to its mean), the model's own standard errors would be wrong if used as-is, so this fallback corrects for that with a robust "sandwich" (Huber–White) variance estimator instead of the model-based one. The results title always states which of the two models actually produced the numbers shown. One known quirk of the modified-Poisson fallback specifically: because the Poisson link has no upper bound, it can imply a fitted probability above 1 for some observations — the robust variance estimator may still provide a useful approximation for relative-risk inference, but predictions near or beyond 1 should be treated as a model-diagnostic warning.
Likelihood ratio test — 2×(log-likelihood of this model − log-likelihood of an intercept-only model), compared to a chi-squared distribution with degrees of freedom equal to the number of coefficients added (one per continuous/ordinal predictor, k−1 per nominal predictor with k categories). This tests whether the predictors jointly improve on a model with none of them — it's the recommended overall significance test, more reliable than the per-coefficient Wald z-test when effects are large or samples are small.
McFadden's pseudo-R² — 1 − (log-likelihood of this model ⁄ log-likelihood of the intercept-only model). It doesn't mean the same thing as R² in linear regression — values of 0.2–0.4 are often considered a good fit for this measure, not a low one.
Convergence — if Newton–Raphson doesn't settle within 100 iterations, or a coefficient grows extremely large, that usually means perfect or near-perfect separation (the predictors sort the outcome too cleanly for a finite estimate to exist) — the result is flagged rather than reported as if it were a stable estimate. For Poisson models, the fitted rate eη is capped at e700 internally during fitting purely to keep a runaway iteration's arithmetic finite (so it fails through this same convergence check instead of producing raw Infinity/NaN); it has no effect on any model that actually converges, but it means the coefficients shown for a flagged, non-converged fit come from an already-capped likelihood, not an uncapped one.
Overdispersion (count Poisson only) — checked with the Pearson dispersion statistic, Σ(yᵢ−μᵢ)²⁄μᵢ divided by the residual degrees of freedom (n − number of parameters). A value well above 1 means the data are more variable than a Poisson model allows; when that happens, this tool automatically widens all standard errors by √(dispersion) (a quasi-Poisson adjustment) rather than reporting overconfident p-values from the plain Poisson model. Relative risk regression for binary outcomes doesn't use this adjustment — when it falls back to modified Poisson, the robust standard error handles the (much larger, and different in kind) variance misspecification directly, and log-binomial's own likelihood-based SE needs no adjustment at all.
Not implemented — interaction terms and negative-binomial regression (a fuller alternative to quasi-Poisson for overdispersion) aren't available in this tool.
Step 1
Step 2
Effect measure
Model
Step 3
Pooled result
Publication-ready
Square area is proportional to each study's weight in the selected model; the diamond marks the pooled estimate and its 95% CI.
Small-study effects
A significant intercept (p < 0.10 is the conventional threshold for this test, given its usually low power) suggests funnel-plot asymmetry — from publication bias, but also possibly from genuine differences between small and large studies. Egger's test needs at least 3 studies and is unreliable with fewer than about 10.
Per-study effect — for each 2×2 table (a, b = intervention events/non-events; c, d = control events/non-events; n₁ = a+b, n₂ = c+d): odds ratio OR = ad⁄bc; risk ratio RR = (a⁄n₁)⁄(c⁄n₂); risk difference RD = a⁄n₁ − c⁄n₂. OR and RR are pooled on the log scale, back-transformed for display.
Zero cells — if any of a study's four cells is 0, that study has 0.5 added to all four cells before any calculation involving it (a commonly used empirical continuity correction) — otherwise its log OR/RR or variance would be undefined. This is applied consistently to that study's contribution to every statistic below, and is flagged in the studies table. It isn't the only correction in use — treatment-arm continuity corrections and methods designed specifically for sparse data exist and can behave differently, particularly when arm sizes are unequal — so treat any pooled result driven by several zero-cell studies with proportionate caution.
Fixed effect — for OR and RR, the Mantel–Haenszel method (weights bd/n or specific to each measure) is used, with the Robins–Breslow–Greenland (OR) or Greenland–Robins (RR) variance — computed from the raw cell counts with no continuity correction (as in RevMan, Stata and R's metafor/meta) — these remain stable even with sparse data and zero cells, which is why they're preferred over inverse-variance weighting for fixed-effect OR/RR. Risk difference uses inverse-variance weighting instead (Mantel–Haenszel is not commonly extended to risk difference in the same way).
Random effects — DerSimonian–Laird: between-study variance τ² is estimated from Cochran's Q by method of moments, then each study is re-weighted by 1⁄(vᵢ+τ²) and pooled by inverse variance. This is a closed-form, non-iterative estimator — it doesn't require the CI to be built from a fitted likelihood, unlike REML, which isn't implemented in this tool.
HKSJ adjustment — when enabled, replaces the standard random-effects variance with one based on the residual variation around the pooled estimate, and uses a t-distribution with k−1 df instead of a normal z — this is generally more conservative (wider CIs) and recommended whenever there are few studies, since the plain DerSimonian–Laird CI is known to be too narrow in that situation.
Heterogeneity — Cochran's Q = Σwᵢ(yᵢ−ȳ)² (fixed-effect inverse-variance weights), compared to a chi-squared distribution with k−1 df. I² = max(0, (Q−df)⁄Q) × 100% estimates the proportion of total variation due to real between-study differences rather than chance — conventionally, under 25% is considered low, 25–75% moderate, and over 75% substantial, though these bands are only a rough guide.
Forest plot — each study's square is centered on its effect estimate, sized by its weight in the selected model, with a horizontal line for its 95% CI; the diamond at the bottom shows the pooled estimate, with its width spanning the pooled 95% CI. RR and OR use a log-transformed x-axis so that equal ratios are equal distances apart; RD uses a linear axis.
Funnel plot — plots each study's effect estimate (x-axis) against its standard error (y-axis, inverted so precise studies sit near the top), with pseudo-95% confidence limits (pooled fixed-effect estimate ± 1.96×SE) drawn as a funnel. Asymmetry can indicate publication bias, but can also reflect genuine heterogeneity — it's a prompt to look closer, not a definitive test on its own. Egger's test formalizes this by regressing the standardized effect (effect⁄SE) on precision (1⁄SE) and testing whether the intercept differs from zero.
Not implemented — REML and other iterative random-effects estimators (Paule–Mandel, empirical Bayes), subgroup analysis, meta-regression, and trim-and-fill aren't available in this tool.
Step 1
Step 2
Choose exactly one Target (what the model predicts) and at least one Feature. Numeric features are standardized (z-score); categorical features are one-hot encoded; binary variables are mapped to 0/1. Meta / ID columns are kept for reference but never enter the model.
| Column | Role | Data type | Summary |
|---|
Step 3
No hyperparameters to set here — the binary and multi-class cases are fit exactly by Newton–Raphson (they converge in a handful of iterations, not a tunable number), and regression is solved directly in closed form. If training doesn't converge, it's because the classes are perfectly or near-perfectly separable, not because of a learning rate or iteration budget.
Hidden layers
Training
Evaluation
Precision, recall, and F1 are macro-averaged — computed per class, then averaged with each class weighted equally, regardless of how common it is in the test set.
Confusion matrix
ROC curve
Actual vs. predicted
Live prediction
Batch prediction
Upload a CSV with the same feature columns (the target column isn't needed). Predictions and probabilities are appended as new columns and offered as a download.
Preprocessing — numeric standardization (mean/SD) is computed from training-set statistics only, never the test set. Categorical features are dummy-coded into k−1 indicator columns against a reference category, matching the GLM tab's convention and avoiding exact collinearity with the intercept; binary variables (features or the target) are mapped to 0/1. One deliberate exception: the list of known categories itself is built from the full uploaded dataset, training and test rows together, not training rows alone — so a category that happens to appear only in the test split still gets its own column instead of crashing the encoder or silently becoming "unseen." This is a conscious trade-off (a stricter train-only vocabulary is more methodologically pure but would need explicit unseen-category handling instead), and its practical effect is small since which categories exist, not their values, is all that crosses the train/test boundary. A category seen only at prediction time (playground or batch) that wasn't in the data at all is encoded as all-zero — effectively "unseen category," treated as the reference level.
Task type — determined automatically from the target's data type: Binary → two-class classification, Categorical → multi-class classification, Numeric → regression. The model list, evaluation metrics, and prediction display all adapt accordingly.
Logistic / softmax regression — a linear model, fit exactly rather than approximately, with no learning-rate or iteration-count hyperparameters to set for any of the three cases: the two-class case uses the same Newton–Raphson (IRLS) engine as the GLM tab; regression uses closed-form ordinary least squares (no iteration involved); and the more-than-two-class (softmax) case uses Newton–Raphson on a k−1 free-parameter reformulation (one class fixed as reference), with the full multinomial Hessian solved at each step. Nominal features are dummy-coded against a reference category (k−1 columns, not k), matching the GLM tab's encoding, so the model stays well-posed regardless of how many categories a feature has.
Decision tree — built by recursive binary splitting (CART), choosing at each node the feature and threshold that most reduces Gini impurity (classification) or variance (regression), down to the chosen max depth.
Random forest — an ensemble of trees, each grown on a bootstrap resample of the training rows; each split is also restricted to a random subset of the features (√p for classification, p/3 for regression, following the standard Breiman recipe) so the trees decorrelate from one another rather than all leaning on the same dominant predictor. For regression, predictions are averaged across trees. For classification, each tree's leaf gives a class-probability vector (not just a single predicted class), and these vectors are averaged across trees; the class with the highest resulting probability is the prediction. This generally trades a little training time for a more stable, less overfit result than a single tree. This is a simplified, educational implementation rather than a drop-in replacement for an established library: there's no out-of-bag error estimate, no feature-importance ranking, and no pruning beyond the minimum-samples-per-split stopping rule.
k-Nearest Neighbors — predicts a new point from the k closest training rows by Euclidean distance (after standardization) — majority class fraction for classification, mean value for regression. No explicit "training" step beyond storing the data.
Neural network — a multilayer perceptron built and trained with TensorFlow.js (loaded from a CDN only when you train one), with your chosen hidden-layer sizes and activation function, Adam optimization at your chosen learning rate, and a sigmoid, softmax, or linear output layer depending on the task. The live loss curve is training loss on a further split of the training data (not the held-out test set), so the test-set evaluation below stays honest.
Evaluation — all metrics are computed on the held-out test set only, never on data the model trained on. The train/test split (and, for the neural network, its internal training/validation split) is stratified by class for classification tasks, so a rare class's proportion is preserved on both sides rather than left to chance. Precision, recall, and F1 are macro-averaged across classes for multi-class problems. The ROC curve and AUC are shown only for two-class problems.
Not implemented — support vector machines, cross-validation / hyperparameter search, feature importance, and REML-style iterative estimators aren't available in this tool.
New module
Upload a separate dataset (no target/outcome needed) and group similar rows together automatically. This runs independently of the supervised workflow above — it has its own data, its own feature choices, and its own results.
Step 1
Step 2
Choose at least 2 Feature columns to cluster on. Numeric features are standardized (z-score); categorical features are one-hot encoded. Mark identifiers or notes as Ignore.
| Column | Role | Data type | Summary |
|---|
Step 3
Step 4
Step 4
DBSCAN has no "number of groups" to set — instead, it groups rows that are densely packed together in the standardized feature space. A point (counting itself) needs at least min. points within radius (eps) of it to anchor a group; anything not reachable from such a point is left ungrouped ("noise"). If everything ends up in one group, lower the radius; if everything ends up as noise, raise it.
Results
Group profile (mean feature values)
Scatter plot
Live assignment
Batch assignment
Upload a CSV with the same feature columns. A Group column is appended to every row and offered as a download.
Algorithm choices — four ways to find structure in the same standardized/encoded feature matrix, each validated independently against synthetic data with a known group structure before being wired in:
K-means — starting from k initial centroids chosen by the k-means++ scheme (spread out rather than picked purely at random, which reliably gives a better starting point), each row is repeatedly assigned to its nearest centroid (Euclidean distance) and each centroid recomputed as the mean of its assigned rows, until assignments stop changing. Runs from several different random starts and keeps the run with the lowest within-cluster sum of squares (inertia), which substantially reduces the chance of an unlucky starting point driving a poor result — 5 restarts while scanning candidate k values below (for speed, since that scan repeats the whole fit up to 9 times), 15 restarts for the final fit once k is chosen. Assumes groups are roughly round and similarly sized in the standardized feature space.
Hierarchical (Ward) — starts with every row as its own group and repeatedly merges the two groups whose merger increases the total within-group sum of squares the least (Ward's criterion), tracked efficiently via the Lance–Williams update formula, until k groups remain. Unlike k-means, the merge sequence is deterministic (no random restarts needed) and tends to cope better with groups of unequal size, though it still favors compact, roughly convex groups and doesn't scale as well to very large datasets (every pairwise distance is tracked, and the cost grows with the cube of the row count) — disabled above 2,000 rows here to avoid freezing the browser tab.
Gaussian mixture (EM) — models the data as a mixture of k multivariate Gaussian "bumps," each with its own mean, covariance (so groups can be elongated or correlated, not just round), and weight. Fit by expectation-maximization: the E-step computes each row's probability of belonging to each component given the current parameters, and the M-step re-estimates the means/covariances/weights from those probabilities, alternating until the log-likelihood stops improving. Standard EM's log-likelihood is monotonically non-decreasing every iteration — checked during validation — with one deliberate exception here: if a component's responsibility collapses to (near) zero, that single component is reinitialized at a random point rather than left to divide by ~0, which can cause a one-iteration dip in the log-likelihood as a trade-off for not crashing or producing a degenerate fit. Runs from several different random starts and keeps the highest-likelihood fit — 2 restarts while scanning candidate k values below (for speed), 5 restarts for the final fit once k is chosen. Because it's a probabilistic model, every row (and every new point) gets a full posterior probability of belonging to each group, not just a single hard label.
DBSCAN — groups points by density rather than distance-to-a-center: a point, counting itself, with at least "min points" total within its radius ("eps") is a core point (matching scikit-learn's min_samples convention), and groups grow outward by chaining together points that are density-reachable from a core point. Points that end up in no group are flagged as noise rather than forced into the nearest one. This is the only one of the four that can find non-round (e.g. crescent-shaped) groups and the only one that doesn't need a target number of groups chosen in advance — but it needs eps and min points set instead, and both parameters are on standardized-feature-space distances, so what counts as "dense" depends on how many features you include. Its neighbor search costs memory proportional to the square of the row count if points are densely packed (worst case with a large radius), so it's disabled above 8,000 rows here.
Suggested number of groups (k-means, hierarchical, Gaussian mixture) — the chosen algorithm is run for every k from 2 up to min(10, n−1), and each is scored with the average silhouette coefficient — for every row, how much closer it is to its own group than to the next-nearest one, averaged across all rows and ranging from −1 (likely misclassified) to +1 (clearly the right group). The k with the highest average silhouette is suggested, but you can override it with the slider — and for the Gaussian mixture specifically, silhouette is a distance-based heuristic borrowed from k-means, not a likelihood-based criterion (such as BIC or AIC) suited to a probabilistic mixture model, so treat its suggested k there as a reasonable starting point rather than a statistically optimal one. DBSCAN doesn't take a k at all — its group count falls out of the eps/min points parameters instead, and its silhouette score (when shown) is computed with noise points excluded, since silhouette isn't defined for an unclustered point.
Preprocessing — numeric features are z-score standardized; categorical features are one-hot encoded (one column per category — full one-hot here, unlike the supervised module's k−1 dummy coding, since there's no intercept term for a category to be collinear with), both using statistics from the uploaded dataset. A category seen only in the playground or a batch file that wasn't in the original data is encoded as all-zero. Mixing numeric and categorical features this way means Euclidean distance treats every one-hot column like any other standardized number — a categorical feature with many levels (each becoming its own column) can end up carrying more weight in the distance calculation than a single continuous feature does, simply because it occupies more dimensions. Results can be sensitive to which categorical features are included and how many levels they have, not just to the algorithm chosen.
Group profile — the mean of each feature within each group, on its original scale (un-standardized) — a quick way to see what distinguishes one group from another. DBSCAN's noise points get their own row rather than being folded into a real group.
Assigning new data — for k-means and hierarchical clustering, a new row (from the playground or a batch file) is assigned to whichever group's centroid it's closest to, with the relative distances shown as a sense of how clear-cut the assignment is. For the Gaussian mixture, it's assigned to the group with the highest posterior probability, with the full probability breakdown shown. DBSCAN itself defines no rule for a new point — that's outside what the algorithm covers — so this is a disclosed heuristic, not part of formal DBSCAN: the nearest training core point within eps is preferred (a core point is what anchors a group in the first place), falling back to the nearest in-cluster point of any kind only if no core point is in range; if nothing is within eps at all, the new point is flagged as noise, the same way an outlier in the original data would have been.
Limitations — all four can be misled by features that aren't actually meaningful for grouping — the choice of which features to include matters as much as the algorithm itself, regardless of which one is picked. There's no ground truth to check a clustering against, unlike the supervised module's held-out test set: these groups describe structure in the data, not a validated prediction.