Kruskal–Wallis H Test

Maths: Statistics for machine learning

2 min read

Published Oct 22 2025, updated Aug 17 2026


40
0
0
0

Machine LearningMathsNumPyPandasPythonStatistics

The Kruskal–Wallis H test is a non-parametric statistical test used to determine whether there are statistically significant differences between the medians of three or more independent groups.

It’s the non-parametric alternative to a one-way ANOVA.


In simple terms:

“The Kruskal–Wallis test checks whether the distributions of three or more groups are the same — without assuming a normal distribution.”




When to Use It

  • Three or more groups - Independent samples
  • Ordinal or continuous data - That do not follow a normal distribution
  • Same shape of distribution - The test assumes group distributions have a similar shape

When not to Use It

  • Paired data - Use the Friedman test instead
  • Normal data - Use ANOVA instead



Example Question

“Do customers in different regions (North, South, East, West) spend the same amount on average?”

If spending data are skewed (e.g., non-normal, outliers), the Kruskal–Wallis test is the best choice.




Hypotheses

  • H₀ (Null Hypothesis) - All group medians are equal (no difference between groups)
  • H₁ (Alternative Hypothesis) - At least one group median is different



How It Works

  • Combine all group data together.
  • Rank all data from smallest to largest (1 = smallest).
  • Compute the sum of ranks (Rᵢ) for each group.
  • Calculate the test statistic H:
Kruskal formula

Where:

  • N = total number of observations
  • Ri​ = sum of ranks for group i
  • ni = size of group i
  1. H follows an approximate chi-squared (χ²) distribution with k − 1 degrees of freedom.

If H is large → group medians differ → reject H₀.




Example in Python

Let’s test if three different marketing campaigns lead to different customer spending.

import numpy as npfrom scipy.stats import kruskal# Example data (non-normal)campaign_A = np.array([45, 50, 52, 60, 61, 62, 65, 70, 72])campaign_B = np.array([40, 42, 48, 51, 55, 57, 59, 61, 63])campaign_C = np.array([52, 55, 58, 60, 63, 65, 66, 68, 70])# Perform Kruskal–Wallis Teststat, p = kruskal(campaign_A, campaign_B, campaign_C)print(f"Kruskal–Wallis H Statistic: {stat:.3f}")print(f"P-value: {p:.4f}")

Interpretation:

  • p < 0.05 → Reject H₀ → At least one group’s median differs.
  • p ≥ 0.05 → Fail to reject H₀ → No significant difference between groups.

Output Example:

Kruskal–Wallis H Statistic: 8.274P-value: 0.0159

Since p < 0.05 → there is a significant difference between at least one group’s distribution.


Visual Results:

Kruskal visualisation

This shows each group’s spread - if one boxplot is clearly higher/lower, that’s what drives the significant difference.





Python code

import pingouin as pgimport pandas as pdimport numpy as np# Example: Comparing performance across 3 metrics (non-normal data)np.random.seed(42)df = pd.DataFrame({    'Metric': np.repeat(['A', 'B', 'C'], 20),    'Performance': np.concatenate([        np.random.exponential(scale=1.0, size=20),        np.random.exponential(scale=1.5, size=20),        np.random.exponential(scale=2.0, size=20)    ])})# Run Kruskal-Wallis testresults = pg.kruskal(data=df, dv='Performance', between='Metric')print(results)

Output:

         Source  ddof1         H     p-uncKruskal  Metric      2  3.649508  0.161257
© 2025 SimpleSteps.guide
AboutFAQPoliciesContact