Runs Test for Randomness
The runs test (Wald-Wolfowitz test) checks whether a sequence of binary observations is randomly ordered or shows systematic patterns.
A run is a consecutive sequence of identical values.
import numpy as np
from scipy.stats import runstest_1samp
import matplotlib.pyplot as plt
# Example: Quality control — is the defect pattern random?
np.random.seed(42)
# Scenario 1: Truly random sequence
random_seq = np.random.choice([0, 1], size=50, p=[0.7, 0.3])
# Scenario 2: Systematic pattern (not random)
pattern_seq = np.array([0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
0,0,0,1,0,0,0,1,0,0])
def runs_test(sequence, label):
"""Manual runs test computation."""
n = len(sequence)
n1 = sequence.sum() # number of 1s
n0 = n - n1 # number of 0s
# Count runs
runs = 1
for i in range(1, n):
if sequence[i] != sequence[i-1]:
runs += 1
# Expected runs and variance under H₀
E_R = 2*n1*n0/n + 1
Var_R = 2*n1*n0*(2*n1*n0 - n) / (n**2 * (n-1))
z = (runs - E_R) / np.sqrt(Var_R)
from scipy import stats as sc
p = 2 * sc.norm.sf(abs(z))
print(f"\n{label}:")
print(f" n₀={n0}, n₁={n1}, Runs={runs}")
print(f" E[R]={E_R:.2f}, Var[R]={Var_R:.4f}")
print(f" z={z:.4f}, p={p:.4f}")
print(f" Decision: {'NOT random (reject H₀)' if p < 0.05 else 'Appears random'}")
return runs, z, p
r1, z1, p1 = runs_test(random_seq, "Random sequence")
r2, z2, p2 = runs_test(pattern_seq, "Systematic pattern")
# Visualize
fig, axes = plt.subplots(2, 1, figsize=(14, 6))
for ax, seq, label, p_val in zip(axes, [random_seq, pattern_seq],
['Random Sequence', 'Systematic Pattern'],
[p1, p2]):
colors = ['steelblue' if x == 0 else 'coral' for x in seq]
ax.bar(range(len(seq)), seq, color=colors, edgecolor='black', linewidth=0.5)
ax.set_title(f'{label} (p={p_val:.4f})')
ax.set_ylabel('Value')
ax.set_yticks([0, 1])
plt.tight_layout()
plt.savefig('runs_test.png', dpi=150)
plt.show()
Key Takeaways
- Runs test checks randomness in binary sequences
- Too few runs: positive autocorrelation (clustering)
- Too many runs: negative autocorrelation (alternating)
- Applications: quality control, testing for systematic trends, auditing
- For continuous data: convert to binary using median as cutpoint, then apply runs test