How to run a Kruskal-Wallis test in SciPy (with Code)
The Short Answer (TL;DR)
Pass independent groups as separate arguments to scipy.stats.kruskal to obtain a tie-corrected H statistic and an approximate p-value. Treat the result as an omnibus rank comparison, and inspect distribution shapes before interpreting it as a difference in medians.
from scipy import stats
groups = [[1, 2, 2, 3, 4, 5], [3, 4, 4, 5, 6, 7], [6, 7, 7, 8, 9, 10]]
print(stats.kruskal(*groups, nan_policy="raise"))
Detailed Implementation
This example uses synthetic data and does not need a network connection. Install the recorded package versions in a separate Python environment before running it.
python -m pip install numpy==2.5.4 scipy==1.18.1
from pathlib import Path
import numpy as np
from scipy import stats
# Independent synthetic groups on a common ordered measurement scale.
groups = [np.array(g, dtype=float) for g in [
[1, 2, 2, 3, 4, 5],
[3, 4, 4, 5, 6, 7],
[6, 7, 7, 8, 9, 10],
]]
if any(g.ndim != 1 or g.size < 5 or not np.isfinite(g).all() for g in groups):
raise ValueError("This example requires at least five finite values per group.")
pooled = np.concatenate(groups)
if np.unique(pooled).size < 2:
raise ValueError("The pooled observations must not all be identical.")
result = stats.kruskal(*groups, nan_policy="raise")
tie_factor = stats.tiecorrect(stats.rankdata(pooled, method="average"))
report = (
f"Group sizes: {[g.size for g in groups]}\n"
f"Tie correction factor: {tie_factor:.6f}\n"
f"H statistic: {result.statistic:.6f}\n"
f"Reference chi-square df: {len(groups)-1}\n"
f"Approximate omnibus p-value: {result.pvalue:.8g}\n"
)
print(report)
Path("kruskal-wallis-output.txt").write_text(report, encoding="utf-8")
The text report contains three sample sizes of six, a tie correction below one, the corrected H statistic and an approximate p-value with two reference degrees of freedom. Independent average-rank arithmetic reproduces the reported statistic and probability.
Which observations can be compared?
Use independent samples with a common ordering and one group label per observation. Repeated measurements from the same units need a paired or repeated-measures method. Rank methods do not remove dependence, selection bias or a poor sampling design. The synthetic example contains six observations per group; that sample size alone does not guarantee an accurate approximation for every population.
Does a small p-value identify different medians?
The omnibus comparison can indicate that some groups tend to have larger ranks. A location or median interpretation needs comparable distribution shapes; different spreads can complicate that reading. Inspect the actual observations and describe the groups before choosing an interpretation. The omnibus p-value does not identify a particular pair or show that every pair differs.
How are ties and small groups handled?
Equal pooled observations receive average ranks, and SciPy corrects H for the resulting ties. The reported p-value uses a chi-square approximation. The documentation gives at least five observations per group as a typical guideline, rather than an accuracy guarantee. Very small or heavily tied samples may need a design-appropriate alternative. All-identical pooled data leave no rank contrast, so the example rejects them.
Mathematical Context
Let N be the pooled sample size, n_j each group size and R_j its pooled rank sum. First compute H0 as 12 divided by N(N+1), multiplied by the sum of R_j squared divided by n_j, then subtract 3(N+1). If a tied value occurs t times, its contribution to the tie adjustment is t cubed minus t. The correction factor is C=1-sum(t^3-t)/(N^3-N), with the entire sum of tie contributions divided by the denominator (N^3-N). SciPy reports H=H0/C. The example independently reconstructs the average ranks and C, then verifies H. For three groups the reference distribution has two degrees of freedom, whose upper-tail probability equals exp(-H/2). Rank magnitudes have no original measurement units.
\[ H=\frac{\frac{12}{N(N+1)}\sum_{j=1}^{k}\frac{R_j^2}{n_j}-3(N+1)}{1-\frac{\sum_\ell(t_\ell^3-t_\ell)}{N^3-N}} \]
Reproducibility
Executed with Python 3.12.14; numpy 2.5.4, scipy 1.18.1. Automated checks confirm the stated output properties.
Primary documentation
- SciPy Kruskal-Wallis assumptions and approximate p-value
- SciPy average ranks
- SciPy tie correction
- NIST Kruskal-Wallis rank-sum statistic
Related guides
For a comparison of two independent groups, run a Mann-Whitney U test in SciPy. State whether the question concerns distributions or a location shift, and check the assumptions needed for that interpretation.