MEDIAN_TEST
Overview
The MEDIAN_TEST
function performs Mood’s median test to determine if two or more independent samples come from populations with the same median. This nonparametric test is useful for comparing medians across groups when the data may not be normally distributed. The test works by calculating the grand median of all samples, then constructing a contingency table of counts above and below the median for each group, and applying Pearson’s chi-squared test to assess whether the medians are equal.
The test statistic is:
where is the observed count in group and category (above/below median), and is the expected count under the null hypothesis.
For more details, see the scipy.stats.median_test documentation .
This wrapper exposes only the most commonly used parameters: the sample data and how to handle ties at the median. Advanced options such as alternative test statistics and correction are not exposed for simplicity. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=MEDIAN_TEST(samples, [ties])
samples
(2D list, required): Table where each column is a sample group and each row is an observation. Must have at least two groups with at least two values each.ties
(string, optional, default=“below”): How to classify values equal to the grand median. Options:"below"
,"above"
, or"ignore"
.
The function returns a single-row 2D array: [statistic, pvalue, median]
, or an error message (string) if the input is invalid. The statistic is the Pearson’s chi-squared value, pvalue is the probability of observing the result under the null hypothesis, and median is the grand median of all samples.
Examples
Example 1: Basic Two Groups
Inputs:
samples | ties | |
---|---|---|
1 | 4 | below |
2 | 5 | |
3 | 6 |
Excel formula:
=MEDIAN_TEST({1,4;2,5;3,6})
Expected output:
statistic | pvalue | median |
---|---|---|
2.667 | 0.102 | 3.500 |
Example 2: Three Groups
Inputs:
samples | ties | ||
---|---|---|---|
1 | 4 | 7 | below |
2 | 5 | 8 | |
3 | 6 | 9 |
Excel formula:
=MEDIAN_TEST({1,4,7;2,5,8;3,6,9})
Expected output:
statistic | pvalue | median |
---|---|---|
6.300 | 0.043 | 5.000 |
Example 3: With Ties Above
Inputs:
samples | ties | |
---|---|---|
1 | 4 | above |
2 | 5 | |
3 | 6 |
Excel formula:
=MEDIAN_TEST({1,4;2,5;3,6}, "above")
Expected output:
statistic | pvalue | median |
---|---|---|
2.667 | 0.102 | 3.500 |
Example 4: With Ties Ignore
Inputs:
samples | ties | |
---|---|---|
1 | 4 | ignore |
2 | 5 | |
3 | 6 |
Excel formula:
=MEDIAN_TEST({1,4;2,5;3,6}, "ignore")
Expected output:
statistic | pvalue | median |
---|---|---|
2.667 | 0.102 | 3.500 |
Python Code
from scipy.stats import median_test as scipy_median_test
from typing import List, Optional, Union
def median_test(samples: List[List[float]], ties: str = "below") -> Union[List[List[Optional[float]]], str]:
"""
Performs Mood’s median test to determine if two or more independent samples come from populations with the same median.
Args:
samples: 2D list of float values. Each column represents a sample group.
ties: How to classify values equal to the grand median ('below', 'above', 'ignore'). Default is 'below'.
Returns:
2D list with a single row: [statistic, pvalue, median], or an error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Validate samples input
if not isinstance(samples, list) or len(samples) < 2:
return "Invalid input: samples must be a 2D list with at least two columns (groups)."
if not all(isinstance(col, list) and len(col) > 0 for col in samples):
return "Invalid input: each sample group must be a non-empty list."
# Check for at least two groups with at least two values each
if sum(len(col) >= 2 for col in samples) < 2:
return "Invalid input: at least two groups must have at least two values each."
# Validate ties
if ties not in ("below", "above", "ignore"):
return "Invalid input: ties must be 'below', 'above', or 'ignore'."
# Flatten and check for valid float values
try:
for col in samples:
for v in col:
if not isinstance(v, (int, float)):
return "Invalid input: all values must be numeric."
except Exception:
return "Invalid input: samples must be a 2D list of floats."
# Run median test
try:
stat, pvalue, median, _ = scipy_median_test(*samples, ties=ties)
# Convert numpy types to native float
def to_native(x):
if hasattr(x, 'item'):
return x.item()
return x
stat, pvalue, median = to_native(stat), to_native(pvalue), to_native(median)
# Disallow nan/inf
for val in (stat, pvalue, median):
if val is None or (isinstance(val, float) and (val != val or val in (float('inf'), float('-inf')))):
return "Invalid output: result contains nan or inf."
return [[stat, pvalue, median]]
except Exception as e:
return f"scipy.stats.median_test error: {e}"