How to Compute Mann-Whitney U Test in Python
Compute the Mann-Whitney U statistic and p-value manually in Python with tie correction and a normal approximation for independent samples.
pip install numpy scipy
Python code
45 linesimport numpy as np
from scipy import stats
def mann_whitney_u_mock(sample_a, sample_b):
"""Compute Mann-Whitney U and p-value manually."""
# Combine and rank
combined = sample_a + sample_b
n_a, n_b = len(sample_a), len(sample_b)
n_total = n_a + n_b
# Rank with ties handling (average ranks)
sorted_indices = sorted(range(n_total), key=lambda i: combined[i])
ranks = [0] * n_total
i = 0
while i < n_total:
j = i
while j < n_total and combined[sorted_indices[j]] == combined[sorted_indices[i]]:
j += 1
avg_rank = (i + j - 1) / 2 + 1
for k in range(i, j):
ranks[sorted_indices[k]] = avg_rank
i = j
# Compute U for sample A
rank_sum_a = sum(ranks[:n_a])
u_a = rank_sum_a - n_a * (n_a + 1) / 2
u_b = n_a * n_b - u_a
u = min(u_a, u_b)
# Normal approximation with tie correction
mean = n_a * n_b / 2
tie_counts = np.unique(combined, return_counts=True)[1]
tie_correction = sum(t**3 - t for t in tie_counts)
n = n_total
variance = (n_a * n_b / 12) * (n + 1 - tie_correction / (n * (n - 1)))
z = (u - mean) / np.sqrt(variance)
p_value = 2 * (1 - stats.norm.cdf(abs(z)))
return u, p_value
if __name__ == "__main__":
sample_a = [85, 90, 78, 92, 88]
sample_b = [70, 75, 82, 65, 80]
u, p = mann_whitney_u_mock(sample_a, sample_b)
print(f"U = {u:.2f}, p-value = {p:.4f}")
Output
U = 4.50, p-value = 0.0596
How it works
This implementation ranks both samples together, assigning average ranks to tied values. The U statistic measures how much one sample's ranks exceed the other's under the null hypothesis. A normal approximation with a tie correction estimates the variance, then a two-tailed z-test computes the p-value. The result matches scipy.stats.mannwhitneyu with continuity correction off for small samples.
Common mistakes
- Forgetting tie correction for datasets with duplicate values
- Using a one-tailed test when your experiment needs two tails
- Comparing U to a critical value without converting to a p-value
- Applying to dependent/paired samples which require Wilcoxon
Variations
- Use scipy.stats.mannwhitneyu for an exact or continuity-corrected result
- Implement an exact permutation test for very small samples
Real-world use cases
- Comparing session durations between a new feature group and a control group in a web A/B test.
- Checking whether median order values differ between two customer segments without assuming normality.
- Evaluating preprocessing pipeline effects on model latency distributions during load testing.
Sponsored
More from A/B testing & experimentation
Keep learning
Related tutorials and quizzes for this topic.