FLIGNER
Overview
The FLIGNER function performs the Fligner-Killeen test, a nonparametric method for testing the null hypothesis that multiple samples come from populations with equal variances. This test is particularly valuable because it is distribution-free when the populations are identical, making it robust to departures from normality.
The Fligner-Killeen test was introduced by Fligner and Killeen (1976) as an alternative to parametric tests like Bartlett’s test. According to a comprehensive simulation study by Conover et al. (1981), the Fligner-Killeen test, along with Levene’s test, demonstrates superior robustness and power compared to other variance homogeneity tests when data deviate from normality.
This implementation uses the scipy.stats.fligner function from the SciPy library. The test computes a test statistic based on the absolute deviations of each observation from a central tendency measure (mean, median, or trimmed mean) of its sample group. The test statistic follows a chi-square distribution under the null hypothesis:
\chi^2 \sim \chi^2_{k-1}
where k is the number of sample groups being compared.
Three variants of the test are available, differing by the measure of central tendency used: - Median (default): Most robust to outliers and non-normality - Mean: Traditional approach, sensitive to outliers - Trimmed mean: Balances robustness with efficiency by trimming extreme values
A small p-value (typically < 0.05) suggests that the population variances differ significantly between groups. This test is commonly used as a preliminary step before conducting ANOVA or other procedures that assume homogeneity of variance. For related tests, see also Bartlett’s test for normal samples and Levene’s test as another robust alternative.
This example function is provided as-is without any representation of accuracy.
Excel Usage
=FLIGNER(samples, fligner_center, trimmed_proportion)
samples(list[list], required): 2D array of sample data. Each column represents a different sample group.fligner_center(str, optional, default: “median”): Central tendency function to use for the test.trimmed_proportion(float, optional, default: 0.05): Proportion to cut from each end when using trimmed mean (0 to 0.5).
Returns (list[list]): 2D list [[statistic, p_value]], or error message string.
Examples
Example 1: Three groups with median center
Inputs:
| samples | fligner_center | ||
|---|---|---|---|
| 1.2 | 2.3 | 2.1 | median |
| 2.5 | 2.7 | 2.8 | |
| 1.9 | 2 | 2.2 |
Excel formula:
=FLIGNER({1.2,2.3,2.1;2.5,2.7,2.8;1.9,2,2.2}, "median")
Expected output:
| Result | |
|---|---|
| 0.5164 | 0.7724 |
Example 2: Three groups with mean center
Inputs:
| samples | fligner_center | ||
|---|---|---|---|
| 1.2 | 2.3 | 2.1 | mean |
| 2.5 | 2.7 | 2.8 | |
| 1.9 | 2 | 2.2 |
Excel formula:
=FLIGNER({1.2,2.3,2.1;2.5,2.7,2.8;1.9,2,2.2}, "mean")
Expected output:
| Result | |
|---|---|
| 5.8586 | 0.0534 |
Example 3: Three groups with trimmed center
Inputs:
| samples | fligner_center | trimmed_proportion | ||
|---|---|---|---|---|
| 1.2 | 2.3 | 2.1 | trimmed | 0.1 |
| 2.5 | 2.7 | 2.8 | ||
| 1.9 | 2 | 2.2 |
Excel formula:
=FLIGNER({1.2,2.3,2.1;2.5,2.7,2.8;1.9,2,2.2}, "trimmed", 0.1)
Expected output:
| Result | |
|---|---|
| 5.8586 | 0.0534 |
Example 4: Uniform variance groups
Inputs:
| samples | fligner_center | ||
|---|---|---|---|
| 1 | 1.1 | 1.2 | median |
| 2 | 2.1 | 2.2 | |
| 3 | 3.1 | 3.2 |
Excel formula:
=FLIGNER({1,1.1,1.2;2,2.1,2.2;3,3.1,3.2}, "median")
Expected output:
| Result | |
|---|---|
| 0.391 | 0.8224 |
Python Code
import math
from scipy.stats import fligner as scipy_fligner
def fligner(samples, fligner_center='median', trimmed_proportion=0.05):
"""
Performs the Fligner-Killeen test for equality of variances across multiple samples.
See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.fligner.html
This example function is provided as-is without any representation of accuracy.
Args:
samples (list[list]): 2D array of sample data. Each column represents a different sample group.
fligner_center (str, optional): Central tendency function to use for the test. Valid options: Mean, Median, Trimmed. Default is 'median'.
trimmed_proportion (float, optional): Proportion to cut from each end when using trimmed mean (0 to 0.5). Default is 0.05.
Returns:
list[list]: 2D list [[statistic, p_value]], or error message string.
"""
def to2d(x):
return [[x]] if not isinstance(x, list) else x
samples = to2d(samples)
if not isinstance(samples, list) or len(samples) < 2:
return "Invalid input: samples must be a 2D list with at least two columns (sample 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."
# Validate all values are numeric
for col in samples:
for val in col:
if not isinstance(val, (int, float)):
return "Invalid input: all sample values must be numeric."
if fligner_center not in ('mean', 'median', 'trimmed'):
return "Invalid input: fligner_center must be 'mean', 'median', or 'trimmed'."
if fligner_center == 'trimmed':
try:
proportiontocut = float(trimmed_proportion)
except (TypeError, ValueError):
return "Invalid input: trimmed_proportion must be a float."
if not (0 <= proportiontocut < 0.5):
return "Invalid input: trimmed_proportion must be between 0 and 0.5."
else:
proportiontocut = 0.05
try:
if fligner_center == 'trimmed':
result = scipy_fligner(*samples, center=fligner_center, proportiontocut=proportiontocut)
else:
result = scipy_fligner(*samples, center=fligner_center)
stat, pvalue = float(result.statistic), float(result.pvalue)
except Exception as e:
return f"scipy.stats.fligner error: {e}"
if math.isnan(stat) or math.isnan(pvalue) or math.isinf(stat) or math.isinf(pvalue):
return "Invalid output: statistic or pvalue is nan or inf."
return [[stat, pvalue]]