The Mann-Whitney U test is a nonparametric alternative to the [independent samples t-test](/tutorials/independent-samples-t-test-with-scipy). It is useful when the groups are independent but the [normality assumption](/tutorials/normality-tests-with-scipy) is questionable or when you want a rank-based comparison. ### Basic Mann-Whitney U Test
import numpy as np
from scipy import stats
np.random.seed(44)
group_a = np.random.exponential(scale=1.0, size=40)
group_b = np.random.exponential(scale=1.9, size=40)
result = stats.mannwhitneyu(group_a, group_b, alternative="two-sided")
print(f"Median of group A: {np.median(group_a):.3f}")
print(f"Median of group B: {np.median(group_b):.3f}")
print(f"U statistic: {result.statistic:.3f}")
print(f"P-value: {result.pvalue:.6f}")### Interpreting the Result
import numpy as np
from scipy import stats
np.random.seed(44)
group_a = np.random.exponential(scale=1.0, size=40)
group_b = np.random.exponential(scale=1.9, size=40)
result = stats.mannwhitneyu(group_a, group_b, alternative="two-sided")
if result.pvalue < 0.05:
print("Reject the null hypothesis: the groups differ in distribution or central tendency.")
else:
print("Fail to reject the null hypothesis: no strong difference was detected.")### Visualizing the Two Groups
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(44)
group_a = np.random.exponential(scale=1.0, size=40)
group_b = np.random.exponential(scale=1.9, size=40)
plt.figure(figsize=(9, 5))
plt.boxplot([group_a, group_b], tick_labels=["Group A", "Group B"])
plt.ylabel("Value")
plt.title("Independent Groups for Mann-Whitney U Test")
plt.grid(axis="y", linestyle="--", alpha=0.4)
plt.show()### Practical Example: Response Times for Two Interfaces
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
np.random.seed(61)
interface_a = np.random.gamma(shape=2.5, scale=180, size=50)
interface_b = np.random.gamma(shape=2.5, scale=300, size=50)
result = stats.mannwhitneyu(interface_a, interface_b, alternative="two-sided")
print(f"Median response time A: {np.median(interface_a):.1f} ms")
print(f"Median response time B: {np.median(interface_b):.1f} ms")
print(f"P-value: {result.pvalue:.6f}")
print("Conclusion: the interfaces differ significantly." if result.pvalue < 0.05 else "Conclusion: no significant difference detected.")
plt.figure(figsize=(9, 5))
plt.hist(interface_a, bins=12, alpha=0.6, label="Interface A")
plt.hist(interface_b, bins=12, alpha=0.6, label="Interface B")
plt.xlabel("Response time (ms)")
plt.ylabel("Count")
plt.title("Response Time Distributions")
plt.legend()
plt.show()### Conclusion The Mann-Whitney U test is a strong choice when you want a robust comparison between two independent groups without relying on normality. A chart helps explain what the rank-based result is capturing.