DUNNETT
Overview
The DUNNETT
function performs Dunnett’s test for multiple comparisons of means against a control group. Dunnett’s test is used in experimental design to compare several treatment groups to a single control group, controlling the family-wise error rate. It is commonly used in pharmaceutical, agricultural, and biological research when the goal is to determine which treatments differ significantly from the control. The test statistic is based on the difference between each treatment mean and the control mean, adjusted for multiple comparisons:
where is the mean of the -th treatment group, is the mean of the control group, is the pooled variance, and is the sample size per group. For more details, see the scipy.stats.dunnett documentation .
This wrapper simplifies the function to accept a single 2D list for all experimental groups (each column is a group) and a 1D list for the control group. The random generator and advanced options are not exposed. This example function is provided as-is without any representation of accuracy.
Usage
To use the function in Excel:
=DUNNETT(samples, control, [alternative])
samples
(2D list, required): Table of values, where each column is an experimental group and each row is an observation. Must have at least two columns and two rows.control
(1D list, required): List of values for the control group. Must have at least two elements.alternative
(string, optional, default="two-sided"
): Defines the alternative hypothesis. Must be one of"two-sided"
,"less"
, or"greater"
.
The function returns a 2D array with two rows: the first row contains the test statistics for each comparison, and the second row contains the corresponding p-values. If the input is invalid, a string error message is returned.
Examples
Example 1: Basic Case
Inputs:
samples | control | |
---|---|---|
1.2 | 2.1 | 1.1 |
1.5 | 2.3 | 1.4 |
1.3 | 2.2 | 1.2 |
Excel formula:
=DUNNETT({1.2,2.1;1.5,2.3;1.3,2.2}, {1.1,1.4,1.2})
Expected output:
Statistic | Statistic |
---|---|
0.891 | 8.614 |
P-value | P-value |
0.603 | 0.000 |
Example 2: Alternative = “less”
Inputs:
samples | control | alternative | |
---|---|---|---|
1.2 | 2.1 | 1.1 | less |
1.5 | 2.3 | 1.4 | |
1.3 | 2.2 | 1.2 |
Excel formula:
=DUNNETT({1.2,2.1;1.5,2.3;1.3,2.2}, {1.1,1.4,1.2}, "less")
Expected output:
Statistic | Statistic |
---|---|
0.891 | 8.614 |
P-value | P-value |
0.907 | 1.000 |
Example 3: Alternative = “greater”
Inputs:
samples | control | alternative | |
---|---|---|---|
1.2 | 2.1 | 1.1 | greater |
1.5 | 2.3 | 1.4 | |
1.3 | 2.2 | 1.2 |
Excel formula:
=DUNNETT({1.2,2.1;1.5,2.3;1.3,2.2}, {1.1,1.4,1.2}, "greater")
Expected output:
Statistic | Statistic |
---|---|
0.891 | 8.614 |
P-value | P-value |
0.314 | 0.000 |
Example 4: All Arguments Specified
Inputs:
samples | control | alternative | |
---|---|---|---|
1.2 | 2.1 | 1.1 | two-sided |
1.5 | 2.3 | 1.4 | |
1.3 | 2.2 | 1.2 |
Excel formula:
=DUNNETT({1.2,2.1;1.5,2.3;1.3,2.2}, {1.1,1.4,1.2}, "two-sided")
Expected output:
Statistic | Statistic |
---|---|
0.891 | 8.614 |
P-value | P-value |
0.603 | 0.000 |
Python Code
from scipy.stats import dunnett as scipy_dunnett
import numpy as np
from typing import List, Optional, Union
def dunnett(samples: List[List[float]], control: List[float], alternative: str = 'two-sided') -> Union[List[List[Optional[float]]], str]:
"""
Performs Dunnett's test for multiple comparisons of means against a control group.
Args:
samples: 2D list of float values. Each column is an experimental group. Must be a 2D list with at least two columns and two rows.
control: 1D list of float values. The control group.
alternative: Defines the alternative hypothesis ('two-sided', 'less', 'greater'). Default is 'two-sided'.
Returns:
2D list with two rows: first row contains test statistics, second row contains p-values for each comparison, or an error message (str) if input is invalid.
This example function is provided as-is without any representation of accuracy.
"""
# Validate samples
if not isinstance(samples, list) or len(samples) < 2 or not all(isinstance(row, list) for row in samples):
return "Invalid input: samples must be a 2D list with at least two rows."
n_rows = len(samples)
n_cols = len(samples[0]) if n_rows > 0 else 0
if n_cols < 2 or n_rows < 2:
return "Invalid input: samples must be a 2D list with at least two columns and two rows."
for row in samples:
if len(row) != n_cols:
return "Invalid input: all rows in samples must have the same number of columns."
# Transpose to columns (groups)
try:
groups = [[float(samples[row][col]) for row in range(n_rows)] for col in range(n_cols)]
except Exception:
return "Invalid input: samples must contain only numeric values."
# Validate control
if not isinstance(control, list) or len(control) < 2:
return "Invalid input: control must be a list with at least two elements."
try:
control_group = [float(x) for x in control]
except Exception:
return "Invalid input: control must contain only numeric values."
# Validate alternative
if alternative not in ('two-sided', 'less', 'greater'):
return "Invalid input: alternative must be 'two-sided', 'less', or 'greater'."
# Run Dunnett's test with fixed random seed for reproducible results
try:
rng = np.random.default_rng(42) # Fixed seed for reproducibility
result = scipy_dunnett(*groups, control=control_group, alternative=alternative, rng=rng)
except Exception as e:
return f"scipy.stats.dunnett error: {e}"
# Extract statistics and p-values
try:
stat = result.statistic
pvals = result.pvalue
stat_list = stat.tolist() if hasattr(stat, 'tolist') else list(stat)
pvals_list = pvals.tolist() if hasattr(pvals, 'tolist') else list(pvals)
# Replace nan/inf with None
for arr in [stat_list, pvals_list]:
for i in range(len(arr)):
v = arr[i]
if v is None:
continue
if isinstance(v, float):
if v != v or v == float('inf') or v == float('-inf'):
arr[i] = None
return [stat_list, pvals_list]
except Exception as e:
return f"Error extracting results: {e}"