All examples · Example 4 of 34
Violin Plot: Cell Viability
Cell viability (%) across five drug concentrations (n = 30 wells each); violins show the density with an inner IQR box and median.

Key findings
- Viability falls from 98.43% to 24.96% across the dose range (ANOVA F = 288.8, p = 5.6 × 10⁻⁶⁸).
- Spread grows with dose — variance ratio 6.78, Levene p = 1.2 × 10⁻⁶ — so the rank-based Kruskal–Wallis (p = 3.5 × 10⁻²⁷) and Welch comparisons are the robust ones to report.
- Against vehicle, 4 of 4 doses remain significant after Holm correction.
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 |
|---|---|---|---|---|---|---|---|---|---|
| 0 µM | 30 | 98.43 | 5.714 | 1.043 | 97.95 | 94.12 – 102.1 | 86.9 – 110 | 0.183 | -0.577 |
| 0.1 µM | 30 | 91.47 | 7.638 | 1.395 | 90.65 | 87.1 – 95.5 | 76.4 – 108.6 | 0.244 | 0.0182 |
| 1 µM | 30 | 79.53 | 7.828 | 1.429 | 79.7 | 73.25 – 84.17 | 66 – 97.1 | 0.311 | -0.349 |
| 10 µM | 30 | 50.42 | 10.74 | 1.96 | 51.9 | 42.83 – 58.12 | 26.8 – 71.2 | -0.25 | -0.215 |
| 100 µM | 30 | 24.96 | 14.88 | 2.717 | 27.3 | 12.03 – 35.77 | 0 – 53.4 | -0.0442 | -1.12 |
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 |
|---|---|---|---|---|---|---|---|---|
| 0 µM | 30 | 0.9815 | 0.86 | 0.2376 | 0.76 | 0.1053 | 0.54 | Consistent with normal |
| 0.1 µM | 30 | 0.9793 | 0.81 | 0.2847 | 0.60 | 0.09935 | 0.63 | Consistent with normal |
| 1 µM | 30 | 0.9746 | 0.67 | 0.2444 | 0.74 | 0.07337 | 0.95 | Consistent with normal |
| 10 µM | 30 | 0.9864 | 0.96 | 0.1663 | 0.93 | 0.07325 | 0.95 | Consistent with normal |
| 100 µM | 30 | 0.9571 | 0.26 | 0.4866 | 0.21 | 0.1108 | 0.46 | 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) | 9.2 | 1.2 × 10⁻⁶ | 6.78 | Variances differ |
| Bartlett | 31.45 | 2.5 × 10⁻⁶ | 6.78 | Variances differ |
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
- Variances differ: use Welch's t-test (stats.ttest default) or stats.kruskal rather than the pooled-variance alternatives.
- Bartlett's test assumes normality and is badly inflated when that fails — confirm with stats.normality, or use method='levene'.
Outlier screen
Five detectors with different assumptions. Grubbs tests the single most extreme point, generalised ESD looks for up to several (immune to masking), Dixon's Q is the small-sample chemistry test, modified-z uses the median and MAD so needs no normality, and the IQR rule is Tukey's boxplot fence. LabTools flags points; it never deletes them.
| Method | 0 µM | 0.1 µM | 1 µM | 10 µM | 100 µM |
|---|---|---|---|---|---|
| Grubbs | none | none | none | none | none |
| Generalised ESD | none | none | none | none | none |
| Dixon's Q | none | none | none | none | none |
| Modified z (MAD) | none | none | none | none | none |
| IQR fences (1.5×) | none | 1 (108.6) | none | none | none |
LabTools calls (5)
stats.outlierslabtools stats outliers --groups @groups.json --method grubbs
stats.outlierslabtools stats outliers --groups @groups.json --method generalized-esd --max-outliers 5
stats.outlierslabtools stats outliers --groups @groups.json --method dixon-q
stats.outlierslabtools stats outliers --groups @groups.json --method modified-z
stats.outlierslabtools stats outliers --groups @groups.json --method iqr
The same method is available as an MCP tool (stats_outliers) and from the desktop app's statistics panel.
LabTools notes
- Flagged points are candidates, not verdicts, and nothing has been removed. Look for a physical cause before excluding anything; if there is none, keep the point and use a robust test instead. Any exclusion must be reported.
- The IQR rule is descriptive — it has no p-value and flags roughly 0.7% of a perfectly normal sample by construction.
Confidence intervals for the mean
t-based intervals: the range of population means these data are consistent with. Report them alongside p-values — an interval shows the size of an effect, a p-value does not.
| Group | n | Mean | 95% CI |
|---|---|---|---|
| 0 µM | 30 | 98.43 | [96.29, 100.6] |
| 0.1 µM | 30 | 91.47 | [88.62, 94.33] |
| 1 µM | 30 | 79.53 | [76.6, 82.45] |
| 10 µM | 30 | 50.42 | [46.41, 54.43] |
| 100 µM | 30 | 24.96 | [19.41, 30.52] |
LabTools calls (2)
stats.cilabtools stats ci --data @0_µM.json --conf-level 0.95
stats.cilabtools stats ci --data @100_µM.json --conf-level 0.95
The same method is available as an MCP tool (stats_ci) and from the desktop app's statistics panel.
Do the groups differ? (omnibus tests)
One-way ANOVA compares means and assumes normal residuals with equal variances; Kruskal–Wallis compares ranks and assumes neither. Both only say the groups differ somewhere — the pairwise table below says where.
| Test | Statistic | df | p | Effect size |
|---|---|---|---|---|
| One-way ANOVA | F = 288.8 | 4, 145 | 5.6 × 10⁻⁶⁸ | ω² = 0.885 · η² = 0.888 · Cohen's f = 2.82 |
| Kruskal–Wallis H | H = 130.2 | 4 | 3.5 × 10⁻²⁷ | ε² = 0.874 |
LabTools calls (2)
stats.anovalabtools stats anova --groups @groups.json
stats.kruskallabtools stats kruskal --groups @groups.json
The same method is available as an MCP tool (stats_anova) and from the desktop app's statistics panel.
LabTools notes
- Group variances are unequal (Levene W = 9.2000, p = 0.0000 < 0.05); the equal-variance assumption of this test is violated. Use the Welch variant instead.
Which groups differ? (pairwise, corrected)
4 comparisons (each group against 0 µM), each run as a Welch t-test and a Mann–Whitney test. Testing many pairs inflates false positives, so every p-value is corrected with Holm (family-wise) and Benjamini–Hochberg (false-discovery rate) through stats.adjust.
| Comparison | Mean diff. | 95% CI | Hedges' g | Welch p | Holm | BH | Mann–Whitney p | Holm | Cliff's δ |
|---|---|---|---|---|---|---|---|---|---|
| 0 µM vs 0.1 µM | 6.953 | [3.461, 10.45] | 1.02 | 0.0002 | 0.0002 | 0.0002 | 0.0003 | 0.0003 | 0.547 |
| 0 µM vs 1 µM | 18.9 | [15.35, 22.45] | 2.72 | 7.9 × 10⁻¹⁵ | 1.6 × 10⁻¹⁴ | 1.0 × 10⁻¹⁴ | 3.2 × 10⁻¹⁰ | 6.3 × 10⁻¹⁰ | 0.947 |
| 0 µM vs 10 µM | 48 | [43.53, 52.48] | 5.51 | 3.9 × 10⁻²⁵ | 1.6 × 10⁻²⁴ | 8.9 × 10⁻²⁵ | 3.0 × 10⁻¹¹ | 1.2 × 10⁻¹⁰ | 1 |
| 0 µM vs 100 µM | 73.46 | [67.57, 79.36] | 6.43 | 4.5 × 10⁻²⁵ | 1.6 × 10⁻²⁴ | 8.9 × 10⁻²⁵ | 3.0 × 10⁻¹¹ | 1.2 × 10⁻¹⁰ | 1 |
LabTools calls (3)
stats.ttestlabtools stats ttest --a @0_µM.json --b @0.1_µM.json --test welch --no-assumption-checks
stats.mannwhitneylabtools stats mannwhitney --a @0_µM.json --b @0.1_µM.json
stats.adjustlabtools stats adjust --p-values @p_values.json --labels @labels.json --method holm
The same method is available as an MCP tool (stats_ttest) and from the desktop app's statistics panel.
Design sensitivity
LabTools calls (2)
stats.powerlabtools stats power --n1 30 --n2 30 --mode mde --power 0.8
stats.powerlabtools stats power --n1 30 --n2 30 --effect-size 0.5
The same method is available as an MCP tool (stats_power) and from the desktop app's statistics panel.
Methods paragraph
Written to go straight into a manuscript.
Normality held within groups (Shapiro–Wilk p ≥ 0.26) but variances were unequal (Levene W = 9.2, p < 0.0001), so groups were compared by Kruskal–Wallis (H = 130.2, df = 4, p < 0.0001, ε² = 0.87). One-way ANOVA agreed (F(4,145) = 288.8, ω² = 0.88).
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.