All examples · Example 29 of 34
ROC Curve: Diagnostic Biomarker
Receiver operating characteristic curve for a biomarker score distinguishing 123 cases from 177 controls; dashed line is chance.

Key findings
- AUC = 0.846, computed from the Mann–Whitney U statistic (123 cases, 177 controls), p = 1.9 × 10⁻²⁴ against chance (AUC = 0.5).
- Hedges' g = 1.44: the case and control score distributions still overlap substantially, which is why a single cut-off trades sensitivity against specificity.
Descriptive statistics
Location, spread and shape for every group — the first thing to read before choosing a test. Skewness near 0 and excess kurtosis near 0 are what a normal distribution looks like.
| Group | n | Mean | SD | SEM | Median | Q1 – Q3 | Min – Max | Skewness | Excess kurtosis |
|---|---|---|---|---|---|---|---|---|---|
| Cases | 123 | 1.303 | 0.9663 | 0.08712 | 1.318 | 0.649 – 1.943 | -0.992 – 3.561 | 0.0718 | -0.373 |
| Controls | 177 | -0.0657 | 0.9338 | 0.07019 | -0.085 | -0.582 – 0.574 | -2.918 – 2.69 | -0.184 | 0.539 |
LabTools call
stats.describelabtools stats describe --groups @groups.json
The same method is available as an MCP tool (stats_describe) and from the desktop app's statistics panel.
Normality
Three tests of the same question — could these values come from a normal distribution? Shapiro–Wilk has the best power at bench sample sizes, Anderson–Darling is more sensitive in the tails, and Kolmogorov–Smirnov (Lilliefors-corrected) is included for comparability with older papers. A significant p means normality is rejected.
| Group | n | Shapiro–Wilk W | p | Anderson–Darling A² | p | K–S D | p | Verdict |
|---|---|---|---|---|---|---|---|---|
| Cases | 123 | 0.9918 | 0.69 | 0.1989 | 0.88 | 0.04325 | 0.83 | Consistent with normal |
| Controls | 177 | 0.9913 | 0.36 | 0.353 | 0.46 | 0.04979 | 0.35 | Consistent with normal |
LabTools calls (3)
stats.normalitylabtools stats normality --groups @groups.json --method shapiro-wilk
stats.normalitylabtools stats normality --groups @groups.json --method anderson-darling
stats.normalitylabtools stats normality --groups @groups.json --method kolmogorov-smirnov
The same method is available as an MCP tool (stats_normality) and from the desktop app's statistics panel.
Equal variances
Student's t and one-way ANOVA assume every group has the same spread. LabTools' Levene test uses deviations from the group median (the Brown–Forsythe form), which stays reliable on skewed data; Bartlett's test is more powerful but only trustworthy when the data are normal. A significant p means the equal-variance assumption fails — prefer Welch's t-test or a rank-based test.
| Test | Statistic | p | Largest / smallest variance | Verdict |
|---|---|---|---|---|
| Levene (Brown–Forsythe, median-centred) | 0.657 | 0.42 | 1.07 | Homogeneous |
| Bartlett | 0.1685 | 0.68 | 1.07 | Homogeneous |
LabTools calls (2)
stats.levenelabtools stats levene --groups @groups.json --method levene
stats.levenelabtools stats levene --groups @groups.json --method bartlett
The same method is available as an MCP tool (stats_levene) and from the desktop app's statistics panel.
LabTools notes
- Non-significant. This test has low power on small samples, so treat this as 'no evidence against equal variances', not as evidence for them.
- Bartlett's test assumes normality and is badly inflated when that fails — confirm with stats.normality, or use method='levene'.
Cases vs controls
The same comparison three ways. Welch's t-test (the LabTools default) does not assume equal variances; Student's pools them; Mann–Whitney compares ranks and needs no normality. When they agree the conclusion is robust to the choice.
| Test | Statistic | df | p | Mean difference (Cases − Controls) | 95% CI of difference |
|---|---|---|---|---|---|
| Welch t-test | t = 12.23 | 256.8 | 2.0 × 10⁻²⁷ | 1.369 | [1.148, 1.589] |
| Student t-test | t = 12.31 | 298 | 2.0 × 10⁻²⁸ | 1.369 | [1.15, 1.587] |
| Mann–Whitney U | U = 18,425 | — | 1.9 × 10⁻²⁴ | — | — |
LabTools calls (3)
stats.ttestlabtools stats ttest --a @Cases.json --b @Controls.json --test welch
stats.ttestlabtools stats ttest --a @Cases.json --b @Controls.json --test student
stats.mannwhitneylabtools stats mannwhitney --a @Cases.json --b @Controls.json
The same method is available as an MCP tool (stats_ttest) and from the desktop app's statistics panel.
Effect sizes — how big, not just whether
| Measure | Estimate | 95% CI | Magnitude |
|---|---|---|---|
| Hedges' g (bias-corrected) | 1.44 | [1.183, 1.697] | very large |
| Cohen's d | 1.44 | — | very large |
| Glass's Δ (scaled by the Cases SD) | 1.42 | — | very large |
| Cliff's δ (non-parametric) | 0.693 | — | large |
LabTools calls (4)
stats.effectsizelabtools stats effectsize --a @Cases.json --b @Controls.json --measure hedges-g
stats.effectsizelabtools stats effectsize --a @Cases.json --b @Controls.json --measure cohens-d
stats.effectsizelabtools stats effectsize --a @Controls.json --b @Cases.json --measure glass-delta
stats.effectsizelabtools stats effectsize --a @Cases.json --b @Controls.json --measure cliffs-delta
The same method is available as an MCP tool (stats_effectsize) and from the desktop app's statistics panel.
Design sensitivity
LabTools calls (2)
stats.powerlabtools stats power --n1 123 --n2 177 --mode mde --power 0.8
stats.powerlabtools stats power --n1 123 --n2 177 --effect-size 0.5
The same method is available as an MCP tool (stats_power) and from the desktop app's statistics panel.
The ROC curve is a Mann–Whitney test
The area under the ROC curve equals the probability that a randomly chosen case scores higher than a randomly chosen control — which is exactly what the Mann–Whitney U statistic counts. AUC = U / (n_cases × n_controls), and Cliff's δ = 2·AUC − 1. So the AUC comes with a p-value for free.
Methods paragraph
Written to go straight into a manuscript.
The biomarker discriminated cases from controls with AUC = 0.846 (Mann–Whitney U = 18,425, p < 0.0001).
Every number on this page was computed by the LabTools statistics engine (version 0.14.3) from the example's CSV on 2026-09-23. Where a value was derived before the data reached LabTools (replicate means, paired differences, log odds ratios), the text says so. The data are simulated from a fixed random seed.
Get started
Run the same analysis on your data
Every test on this page is built into LabTools — from the statistics panel, the command line, or an AI assistant through MCP.