Permutation Tests
Intuition
If the group labels "A" and "B" don't matter (the null hypothesis), then shuffling the labels should produce differences in means just as large as the one we observed, fairly often. If almost no shuffle produces a difference as extreme as the real one, the labels probably do matter.
Precise explanation
- Observed statistic .
- Pool all values. For : shuffle the pool, call the first values "x" and the rest "y", compute .
- Two-sided p-value with the standard +1 correction (counts the observed arrangement, never 0):
Fisher–Yates shuffle (uniform over permutations) using only rng.random():
for i from n-1 down to 1:
j = int(rng.random() * (i + 1)) # 0 <= j <= i
swap items[i], items[j]
Floating-point noise can make differ from in the last bits even for
identical arrangements; compare with a small tolerance (>= abs_obs - 1e-12).
Worked example
x = [5, 6, 7], y = [1, 2, 3]: . Only the 2 of the 20 equally likely splits (x and y swapped) are as extreme, so the exact p-value is 2/20 = 0.1; a Monte Carlo estimate with many shuffles is close to 0.1.
Common mistakes
- Shuffling
xandyseparately (labels never move). - Biased shuffles such as
j = int(rng.random() * n)for every i. - Reporting p = 0.
Why this matters
Permutation tests make almost no distributional assumptions; they also underlie permutation feature importance (XA-08), where shuffling a feature breaks its link with the target.
References
- Think Stats (3rd edition) — Allen B. Downey (
S010) - random — Generate pseudo-random numbers — Python Software Foundation (
S004)