Kruskal-Wallis test calculator with Dunn post-hoc comparisons
Compare three or more groups without assuming normality using the Kruskal-Wallis test: tie-corrected H, p-value, epsilon-squared effect size and Dunn pairwise comparisons.
A clear answer. Here’s how.
All values are ranked together from 1, tied values sharing the average of the ranks they span. With N values, R̄ᵢ the mean rank and nᵢ the size of group i, H = 12 ÷ (N(N + 1)) × Σ nᵢ(R̄ᵢ − (N + 1)/2)², which equals 12 ÷ (N(N + 1)) × Σ Rᵢ²/nᵢ − 3(N + 1) for the rank sums Rᵢ. Ties are corrected for by dividing H by 1 − Σ(t³ − t) ÷ (N³ − N), summed over each set of t tied values, which is what R’s kruskal.test does. H is compared with chi-square on k − 1 degrees of freedom, an approximation that is rough when any group has fewer than about five values; exact tables exist (Spurrier 2003 up to 45 values) but are not provided here. Epsilon-squared, the effect size, is H ÷ ((N² − 1) ÷ (N + 1)) = H ÷ (N − 1), between 0 and 1; it equals R², the share of the variance of the ranks that the groups explain. Dunn’s (1964) test compares two groups by z = (R̄ᵢ − R̄ⱼ) ÷ √([N(N + 1)/12 − Σ(t³ − t) ÷ (12(N − 1))] × (1/nᵢ + 1/nⱼ)), the tie-corrected variance as in FSA’s dunnTest and the dunn.test package, with a two-sided p-value from the standard normal distribution. Holm, Bonferroni or Benjamini–Hochberg then adjust all k(k − 1)/2 p-values together, as R’s p.adjust does; a difference is first group minus second, in the order the groups were entered. Dunn’s test uses the ranks of the whole sample, so it is the natural follow-up to a significant Kruskal–Wallis test, but it is not a test of medians unless the distributions have the same shape. The test assumes independent observations and does not handle repeated measures (use the Friedman test for those), ordered alternatives (the Jonckheere–Terpstra test) or exact p-values. It is a calculator, not a substitute for a statistician when decisions depend on the answer.
How this is checked
5 reference checks passed These 5 cases were run when this page was built, on 20 October 2026, and all reproduce within the stated tolerance. The same cases are part of the automated tests that run on every change to Toolmoz. Engine version 1.
See the checks and where each expected answer comes from
Case 1
- Inputs
- The tool’s default inputs
- Expected, and what Toolmoz gave
- Observations (N) expected 30, Toolmoz 30Groups (k) expected 3, Toolmoz 3Kruskal–Wallis H (tie-corrected) expected 16.842307692307692, Toolmoz 16.842307692307696H without the tie correction expected 15.19741935483871, Toolmoz 15.197419354838711Tie correction factor expected 0.9023359288097886, Toolmoz 0.9023359288097886Degrees of freedom expected 2, Toolmoz 2P-value (chi-square approximation) expected 0.0002201604749000415, Toolmoz 0.0002201604749000414Epsilon-squared expected 0.5807692307692308, Toolmoz 0.5807692307692308Rank sum of Pooh expected 208, Toolmoz 208Mean rank of Piglet expected 6.7, Toolmoz 6.7
- Where the expected answer comes from
- The Likert example in the R Companion, where R prints Kruskal-Wallis chi-squared = 16.842, df = 2, p-value = 0.0002202 and epsilonSquared 0.581 (the R-squared of the ranks, 0.5807692). By hand: the rank sums are 67, 208 and 190 (N = 30); the tied sets have 1, 6, 5, 13 and 5 values, so Σ(t³ − t) = 0 + 210 + 120 + 2184 + 120 = 2634 and the factor is 1 − 2634/26970 = 4056/4495; H without it is 12/930 × (67² + 208² + 190²)/10 − 93 = 11778/775 = 15.1974, so H = 15.1974 ÷ 0.90234 = 16.8423 and ε² = 16.8423/29. With 2 degrees of freedom the chi-square tail is exactly exp(−H/2). Exact fractions in an independent Python script
- Allowed difference
- ±1e-9
Case 2
- Inputs
- The tool’s default inputs
- Expected, and what Toolmoz gave
- Dunn z: Piglet − Pooh expected -3.770241230334107, Toolmoz -3.7702412303341077Dunn p (unadjusted): Piglet − Pooh expected 0.00016308982895998648, Toolmoz 0.00016308982895998523Dunn p (Holm-adjusted): Piglet − Pooh expected 0.0004892694868799594, Toolmoz 0.0004892694868799557Dunn z: Piglet − Tigger expected -3.2889338392276257, Toolmoz -3.2889338392276257Dunn p (Holm-adjusted): Piglet − Tigger expected 0.0020113532139136455, Toolmoz 0.0020113532139136325Dunn z: Pooh − Tigger expected 0.4813073911064818, Toolmoz 0.48130739110648196Dunn p (Holm-adjusted): Pooh − Tigger expected 0.630298044801257, Toolmoz 0.6302980448012567
- Where the expected answer comes from
- Dunn’s test on the Likert example. The R Companion prints FSA::dunnTest output with Z = −3.7702412, −3.2889338 and 0.4813074 and unadjusted p = 0.0001630898, 0.0010056766 and 0.6302980448, and PMCMRplus Holm-adjusted values 0.00049, 0.00201 and 0.63030. Holm: the smallest p × 3, the next × 2 (but not below the first), the largest × 1; z = (R̄ᵢ − R̄ⱼ) ÷ √((30 × 31/12 − 2634/(12 × 29)) × (1/10 + 1/10)) with mean ranks 6.7, 20.8 and 19, computed in an independent Python script
- Allowed difference
- ±1e-9
Case 3
- Inputs
- Pairwise comparisons (Dunn) bh
- Expected, and what Toolmoz gave
- Dunn z: Piglet − Pooh expected -3.7702412, Toolmoz -3.7702412303341077Dunn p (unadjusted): Piglet − Pooh expected 0.0001630898, Toolmoz 0.00016308982895998523Dunn p (Benjamini–Hochberg-adjusted): Piglet − Pooh expected 0.0004892695, Toolmoz 0.0004892694868799557Dunn z: Piglet − Tigger expected -3.2889338, Toolmoz -3.2889338392276257Dunn p (unadjusted): Piglet − Tigger expected 0.0010056766, Toolmoz 0.0010056766069568162Dunn p (Benjamini–Hochberg-adjusted): Piglet − Tigger expected 0.0015085149, Toolmoz 0.0015085149104352245Dunn z: Pooh − Tigger expected 0.4813074, Toolmoz 0.48130739110648196Dunn p (Benjamini–Hochberg-adjusted): Pooh − Tigger expected 0.6302980448, Toolmoz 0.6302980448012567
- Where the expected answer comes from
- The FSA::dunnTest(Likert ~ Speaker, method = “bh”) output printed in the R Companion (Z, P.unadj and P.adj for Piglet − Pooh, Piglet − Tigger and Pooh − Tigger), quoted to the digits printed there
- Allowed difference
- ±0.000001 relative
Case 4
- Inputs
- The data are laid out as rowsGroups and values Normal: 2.9 3.0 2.5 2.6 3.2 Obstructive: 3.8 2.7 4.0 2.4 Asbestosis: 2.8 3.4 3.7 2.2 2.0Pairwise comparisons (Dunn) off
- Expected, and what Toolmoz gave
- Kruskal–Wallis H (tie-corrected) expected 0.7714285714285715, Toolmoz 0.7714285714285716Tie correction factor expected 1, Toolmoz 1Degrees of freedom expected 2, Toolmoz 2P-value (chi-square approximation) expected 0.6799647735788938, Toolmoz 0.6799647735788935Epsilon-squared expected 0.05934065934065934, Toolmoz 0.05934065934065935Rank sum of Normal expected 36, Toolmoz 36Rank sum of Obstructive expected 36, Toolmoz 36Rank sum of Asbestosis expected 33, Toolmoz 33
- Where the expected answer comes from
- The example in R’s kruskal.test documentation from Hollander and Wolfe (1973, p. 116), 14 values with no ties. The rank sums are 36, 36 and 33, so H = 12/(14 × 15) × (36²/5 + 36²/4 + 33²/5) − 3 × 15 = (2/35) × 801 − 45 = 27/35 = 0.771429, the chi-square tail with 2 degrees of freedom is exp(−H/2) = 0.67996 (the documentation’s p-value of 0.68), and ε² = (27/35)/13
- Allowed difference
- ±1e-12
Case 5
- Inputs
- The data are laid out as columnsGroups and values A,B,C 1,2,4 2,3,5 2,4,6Pairwise comparisons (Dunn) off
- Expected, and what Toolmoz gave
- Kruskal–Wallis H (tie-corrected) expected 6.3304347826086955, Toolmoz 6.330434782608695H without the tie correction expected 6.066666666666666, Toolmoz 6.0666666666666655Tie correction factor expected 0.9583333333333334, Toolmoz 0.9583333333333334P-value (chi-square approximation) expected 0.04220496582418192, Toolmoz 0.04220496582418196
- Where the expected answer comes from
- A small case with the tie correction worked by hand. The nine values 1, 2, 2, 2, 3, 4, 4, 5, 6 have ranks 1, 3, 3, 3, 5, 6.5, 6.5, 8, 9, so the rank sums are 7, 14.5 and 23.5 and H without the correction is 12/90 × (7² + 14.5² + 23.5²)/3 − 30 = 91/15. Two sets of ties (three 2s and two 4s) give Σ(t³ − t) = 24 + 6 = 30, so the factor is 1 − 30/720 = 23/24 and H = 91/15 × 24/23 = 728/115 = 6.3304; with 2 degrees of freedom p = exp(−H/2)
- Allowed difference
- ±1e-12
What this shows: the engine reproduces independently worked values for these cases. It does not prove every possible input is right. To test an answer you were given, see how to check a number; to see what is and is not checked across Toolmoz, see the accuracy ledger.
See a worked example
Worked example
A fixed demonstration, separate from the values you enter above.
- The data are laid out as
- One group per line, as “name: values”
- Groups and values
Piglet: 2 4 2 2 1 2 3 2 2 3 Pooh: 3 5 4 4 4 4 4 4 5 5 Tigger: 4 4 4 4 5 3 5 4 4 3
- Column separator
- Detect automatically
- Pairwise comparisons (Dunn)
- Dunn’s test with Holm adjustment
- The table shows
- Dunn pairwise comparisons (when switched on above)
Example result
| Comparison | Mean rank difference | Dunn z | p (unadjusted) | p (Holm-adjusted) |
|---|---|---|---|---|
| Piglet − Pooh | -14.1 | -3.7702 | 0.0001631 | 0.0004893 |
| Piglet − Tigger | -12.3 | -3.2889 | 0.001006 | 0.002011 |
| Pooh − Tigger | 1.8 | 0.4813 | 0.6303 | 0.6303 |
Kruskal–Wallis H = [12 ÷ (N(N + 1)) × Σ Rᵢ²/nᵢ − 3(N + 1)] ÷ [1 − Σ(t³ − t) ÷ (N³ − N)], with Rᵢ the rank sum of group i and t the size of each set of tied values, compared with chi-square on k − 1 degrees of freedom, as R’s kruskal.test does. The chi-square p-value is an approximation that is rough when any group has fewer than about five values; exact tables exist but are not provided here. Epsilon-squared = H ÷ ((N² − 1) ÷ (N + 1)) = H ÷ (N − 1) is the effect size (0 to 1). The test shows that the groups differ in how their values rank, which is a difference of medians only if the distributions have the same shape, and it assumes independent observations. Dunn’s test compares mean ranks: z = (R̄ᵢ − R̄ⱼ) ÷ √([N(N + 1)/12 − Σ(t³ − t) ÷ (12(N − 1))] × (1/nᵢ + 1/nⱼ)), two-sided against the normal distribution, adjusted by the Holm method over all 3 comparisons. Differences are first group minus second, in the order the groups were entered. Groups (size, rank sum, mean rank, median): Piglet (10, 67, 6.7, 2); Pooh (10, 208, 20.8, 4); Tigger (10, 190, 19, 4).