BRUNNERMUNZEL
Overview
The BRUNNERMUNZEL
function performs the Brunner-Munzel nonparametric test for comparing two independent samples, which is robust to differences in variance and distribution between groups. Unlike the Mann-Whitney U test, the Brunner-Munzel test does not assume equal variances and is suitable for heteroscedastic data. The test statistic is computed as:
where is the estimated probability that a randomly selected value from sample is less than a randomly selected value from sample , and is the estimated variance of .
For more details, see the scipy.stats.brunnermunzel documentation .
This wrapper exposes only the most commonly used parameters: x
, y
, alternative
, and distribution
. Input arrays are always flattened to 1D, and options like nan_policy
, axis
, and keepdims
are not supported. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=BRUNNERMUNZEL(x, y, [alternative], [distribution])
x
(2D list, required): First sample data. Must be a rectangular range with at least two rows.y
(2D list, required): Second sample data. Must be a rectangular range with at least two rows.alternative
(string, optional, default=‘two-sided’): Defines the alternative hypothesis. Allowed values:two-sided
,less
,greater
.distribution
(string, optional, default=‘t’): Method to compute p-value. Allowed values:t
,normal
.
The function returns a single-row, two-column array: [statistic, pvalue]
(both floats), or an error message (string) if the input is invalid.
Examples
Example 1: Basic Case
Inputs:
x | y | alternative | distribution | ||
---|---|---|---|---|---|
1.2 | 2.3 | 2.1 | 3.2 | two-sided | t |
3.4 | 4.5 | 4.3 | 5.4 |
Excel formula:
=BRUNNERMUNZEL({1.2,2.3;3.4,4.5}, {2.1,3.2;4.3,5.4})
Expected output:
statistic | pvalue |
---|---|
0.548 | 0.604 |
Example 2: Alternative Hypothesis ‘less’
Inputs:
x | y | alternative | distribution | ||
---|---|---|---|---|---|
1.2 | 2.3 | 2.1 | 3.2 | less | t |
3.4 | 4.5 | 4.3 | 5.4 |
Excel formula:
=BRUNNERMUNZEL({1.2,2.3;3.4,4.5}, {2.1,3.2;4.3,5.4}, "less")
Expected output:
statistic | pvalue |
---|---|
0.548 | 0.302 |
Example 3: Distribution ‘normal’
Inputs:
x | y | alternative | distribution | ||
---|---|---|---|---|---|
1.2 | 2.3 | 2.1 | 3.2 | two-sided | normal |
3.4 | 4.5 | 4.3 | 5.4 |
Excel formula:
=BRUNNERMUNZEL({1.2,2.3;3.4,4.5}, {2.1,3.2;4.3,5.4}, "two-sided", "normal")
Expected output:
statistic | pvalue |
---|---|
0.548 | 0.584 |
Example 4: All Arguments Specified
Inputs:
x | y | alternative | distribution | ||
---|---|---|---|---|---|
1.2 | 2.3 | 2.1 | 3.2 | greater | t |
3.4 | 4.5 | 4.3 | 5.4 |
Excel formula:
=BRUNNERMUNZEL({1.2,2.3;3.4,4.5}, {2.1,3.2;4.3,5.4}, "greater", "t")
Expected output:
statistic | pvalue |
---|---|
0.548 | 0.698 |
Python Code
from scipy.stats import brunnermunzel as scipy_brunnermunzel
from typing import List, Union
def brunnermunzel(x: List[List[float]], y: List[List[float]], alternative: str = 'two-sided', distribution: str = 't') -> Union[List[List[float]], str]:
"""
Computes the Brunner-Munzel nonparametric test for two independent samples.
Args:
x: 2D list of float values. First sample data.
y: 2D list of float values. Second sample data.
alternative: Defines the alternative hypothesis ('two-sided', 'less', 'greater'). Default is 'two-sided'.
distribution: Method to compute p-value ('t' or 'normal'). Default is 't'.
Returns:
2D list with a single row: [statistic, pvalue], or an error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Validate x and y are 2D lists with at least two rows
if not (isinstance(x, list) and all(isinstance(row, list) for row in x) and len(x) >= 2):
return "Invalid input: x must be a 2D list with at least two rows."
if not (isinstance(y, list) and all(isinstance(row, list) for row in y) and len(y) >= 2):
return "Invalid input: y must be a 2D list with at least two rows."
# Flatten x and y
try:
x_flat = [float(item) for row in x for item in row]
y_flat = [float(item) for row in y for item in row]
except Exception:
return "Invalid input: x and y must contain only numeric values."
if len(x_flat) < 2 or len(y_flat) < 2:
return "Invalid input: x and y must each contain at least two values."
# Validate alternative
if alternative not in ('two-sided', 'less', 'greater'):
return "Invalid input: alternative must be 'two-sided', 'less', or 'greater'."
# Validate distribution
if distribution not in ('t', 'normal'):
return "Invalid input: distribution must be 't' or 'normal'."
import math
try:
result = scipy_brunnermunzel(x_flat, y_flat, alternative=alternative, distribution=distribution)
stat, pval = float(result.statistic), float(result.pvalue)
# If result is nan/inf and distribution is 't', retry with 'normal'
if distribution == 't' and (
(math.isnan(stat) or math.isinf(stat)) or
(math.isnan(pval) or math.isinf(pval))
):
try:
result2 = scipy_brunnermunzel(x_flat, y_flat, alternative=alternative, distribution='normal')
stat2, pval2 = float(result2.statistic), float(result2.pvalue)
if any([
math.isnan(stat2) or math.isinf(stat2),
math.isnan(pval2) or math.isinf(pval2)
]):
return "Invalid result: statistic or pvalue is NaN or infinite."
return [[stat2, pval2]]
except Exception as e2:
return f"scipy.stats.brunnermunzel error (normal fallback): {e2}"
# Disallow nan/inf
if any([
math.isnan(stat) or math.isinf(stat),
math.isnan(pval) or math.isinf(pval)
]):
return "Invalid result: statistic or pvalue is NaN or infinite."
return [[stat, pval]]
except Exception as e:
return f"scipy.stats.brunnermunzel error: {e}"