scipy.stats.

levene#

scipy.stats.levene(*samples, center='median', proportiontocut=0.05, axis=0, nan_policy='propagate', keepdims=False)[源代码][源代码]#

执行 Levene 检验以检验方差是否相等。

Levene 检验测试了所有输入样本来自具有相同方差的总体的零假设。Levene 检验是 Bartlett 检验 bartlett 的替代方法,适用于存在显著偏离正态性的情况。

参数:
示例1, 示例2, …array_like

样本数据,可能具有不同的长度。仅接受一维样本。

中心{‘mean’, ‘median’, ‘trimmed’}, 可选

在测试中使用数据的哪个函数。默认是 ‘中位数’。

proportiontocutfloat, 可选

center 为 ‘trimmed’ 时,这给出了从每一端剪切的数据点的比例。(参见 scipy.stats.trim_mean。)默认值为 0.05。

int 或 None, 默认值: 0

如果是一个整数,表示输入数据中要计算统计量的轴。输入数据的每个轴切片(例如行)的统计量将出现在输出的相应元素中。如果为 None,则在计算统计量之前会将输入数据展平。

nan_policy{‘propagate’, ‘omit’, ‘raise’}

定义如何处理输入的 NaN。

  • propagate: 如果在计算统计量的轴切片(例如行)中存在 NaN,则输出的相应条目将为 NaN。

  • omit: 在执行计算时,NaN 将被省略。如果在计算统计量的轴切片中剩余的数据不足,则输出的相应条目将为 NaN。

  • raise: 如果存在 NaN,将引发 ValueError

keepdimsbool, 默认值: False

如果设置为True,被减少的轴将作为尺寸为1的维度保留在结果中。通过此选项,结果将正确地与输入数组进行广播。

返回:
统计浮动

测试统计量。

p值浮动

测试的 p 值。

参见

fligner

一种用于检验 k 个方差相等的非参数检验

bartlett

正态样本中k个方差相等的参数检验

注释

Levene检验有三种变体。这些变体及其推荐用途是:

  • ‘median’ : 推荐用于偏斜(非正态)分布

  • ‘mean’ : 推荐用于对称、适度尾部分布的情况。

  • ‘trimmed’ : 推荐用于重尾分布。

在Levene的原始文章中提出了使用均值的测试版本([2]),而中位数和修整均值则由Brown和Forsythe研究([3]),有时也被称为Brown-Forsythe测试。

从 SciPy 1.9 开始,np.matrix 输入(不推荐用于新代码)在计算执行前被转换为 np.ndarray。在这种情况下,输出将是一个标量或适当形状的 np.ndarray,而不是一个 2D 的 np.matrix。同样,虽然掩码数组的掩码元素被忽略,但输出将是一个标量或 np.ndarray,而不是一个 mask=False 的掩码数组。

参考文献

[2]

Levene, H. (1960). 在《概率与统计贡献:纪念Harold Hotelling的论文集》中,I. Olkin等人编辑,斯坦福大学出版社,第278-292页。

[3]

Brown, M. B. 和 Forsythe, A. B. (1974), 《美国统计协会杂志》, 69, 364-367

[4]

C.I. BLISS (1952), 《生物测定的统计学:特别参考维生素》,第499-503页,DOI:10.1016/C2013-0-12584-6

[5]

B. Phipson and G. K. Smyth. “Permutation P-values Should Never Be Zero: Calculating Exact P-values When Permutations Are Randomly Drawn.” Statistical Applications in Genetics and Molecular Biology 9.1 (2010).

[6]

Ludbrook, J., & Dudley, H. (1998). 为什么置换检验在生物医学研究中优于t检验和F检验。美国统计学家, 52(2), 127-132.

示例

[4] 中,研究了维生素C对豚鼠牙齿生长的影响。在一个对照研究中,60个受试者被分为小剂量、中剂量和大剂量组,分别接受每日0.5、1.0和2.0毫克的维生素C剂量。42天后,测量了牙齿的生长情况。

下面的 small_dosemedium_doselarge_dose 数组记录了三个组在微米单位的牙齿生长测量值。

>>> import numpy as np
>>> small_dose = np.array([
...     4.2, 11.5, 7.3, 5.8, 6.4, 10, 11.2, 11.2, 5.2, 7,
...     15.2, 21.5, 17.6, 9.7, 14.5, 10, 8.2, 9.4, 16.5, 9.7
... ])
>>> medium_dose = np.array([
...     16.5, 16.5, 15.2, 17.3, 22.5, 17.3, 13.6, 14.5, 18.8, 15.5,
...     19.7, 23.3, 23.6, 26.4, 20, 25.2, 25.8, 21.2, 14.5, 27.3
... ])
>>> large_dose = np.array([
...     23.6, 18.5, 33.9, 25.5, 26.4, 32.5, 26.7, 21.5, 23.3, 29.5,
...     25.5, 26.4, 22.4, 24.5, 24.8, 30.9, 26.4, 27.3, 29.4, 23
... ])

levene 统计量对样本间方差的差异敏感。

>>> from scipy import stats
>>> res = stats.levene(small_dose, medium_dose, large_dose)
>>> res.statistic
0.6457341109631506

当方差差异较大时,统计值往往会较高。

我们可以通过将统计量的观测值与零分布进行比较来测试各组间方差的不等性:零分布是指在零假设下,即三组总体方差相等的假设下,统计量值的分布。

在这个测试中,零分布遵循如下所示的 F 分布。

>>> import matplotlib.pyplot as plt
>>> k, n = 3, 60   # number of samples, total number of observations
>>> dist = stats.f(dfn=k-1, dfd=n-k)
>>> val = np.linspace(0, 5, 100)
>>> pdf = dist.pdf(val)
>>> fig, ax = plt.subplots(figsize=(8, 5))
>>> def plot(ax):  # we'll reuse this
...     ax.plot(val, pdf, color='C0')
...     ax.set_title("Levene Test Null Distribution")
...     ax.set_xlabel("statistic")
...     ax.set_ylabel("probability density")
...     ax.set_xlim(0, 5)
...     ax.set_ylim(0, 1)
>>> plot(ax)
>>> plt.show()
../../_images/scipy-stats-levene-1_00_00.png

比较通过 p 值量化:零分布中大于或等于统计量观测值的值的比例。

>>> fig, ax = plt.subplots(figsize=(8, 5))
>>> plot(ax)
>>> pvalue = dist.sf(res.statistic)
>>> annotation = (f'p-value={pvalue:.3f}\n(shaded area)')
>>> props = dict(facecolor='black', width=1, headwidth=5, headlength=8)
>>> _ = ax.annotate(annotation, (1.5, 0.22), (2.25, 0.3), arrowprops=props)
>>> i = val >= res.statistic
>>> ax.fill_between(val[i], y1=0, y2=pdf[i], color='C0')
>>> plt.show()
../../_images/scipy-stats-levene-1_01_00.png
>>> res.pvalue
0.5280694573759905

如果 p 值是“小”的——也就是说,如果从具有相同方差的分布中抽取数据产生如此极端的统计值的概率很低——这可能被视为反对零假设而支持备择假设的证据:各组的方差不相等。注意:

  • 反之则不然;也就是说,测试并不用于为零假设提供证据。

  • 被视为“小”的值的阈值是在分析数据之前应做出的选择 [5] ,需要考虑假阳性(错误地拒绝原假设)和假阴性(未能拒绝错误的原假设)的风险。

  • 小的p值并不是*大*效应的证据;相反,它们只能提供“显著”效应的证据,这意味着它们在零假设下不太可能发生。

请注意,F 分布提供了零分布的渐近近似。对于小样本,进行置换检验可能更为合适:在零假设下,所有三个样本都来自同一总体,每个测量值在三个样本中的任何一个中被观察到的可能性是相等的。因此,我们可以通过在许多随机生成的将观察值分配到三个样本的分区下计算统计量,来形成一个随机的零分布。

>>> def statistic(*samples):
...     return stats.levene(*samples).statistic
>>> ref = stats.permutation_test(
...     (small_dose, medium_dose, large_dose), statistic,
...     permutation_type='independent', alternative='greater'
... )
>>> fig, ax = plt.subplots(figsize=(8, 5))
>>> plot(ax)
>>> bins = np.linspace(0, 5, 25)
>>> ax.hist(
...     ref.null_distribution, bins=bins, density=True, facecolor="C1"
... )
>>> ax.legend(['aymptotic approximation\n(many observations)',
...            'randomized null distribution'])
>>> plot(ax)
>>> plt.show()
../../_images/scipy-stats-levene-1_02_00.png
>>> ref.pvalue  # randomized test p-value
0.4559  # may vary

需要注意的是,这里计算的p值与上面`levene`返回的渐近近似值之间存在显著分歧。从排列检验中可以严格得出的统计推断是有限的;尽管如此,它们在许多情况下可能是首选的方法 [6]

以下是另一个拒绝零假设的通用示例。

测试列表 abc 是否来自具有相等方差的总体。

>>> a = [8.88, 9.12, 9.04, 8.98, 9.00, 9.08, 9.01, 8.85, 9.06, 8.99]
>>> b = [8.88, 8.95, 9.29, 9.44, 9.15, 9.58, 8.36, 9.18, 8.67, 9.05]
>>> c = [8.95, 9.12, 8.95, 8.85, 9.03, 8.84, 9.07, 8.98, 8.86, 8.98]
>>> stat, p = stats.levene(a, b, c)
>>> p
0.002431505967249681

较小的p值表明总体方差不相等。

考虑到 b 的样本方差远大于 ac 的样本方差,这一点并不令人惊讶:

>>> [np.var(x, ddof=1) for x in [a, b, c]]
[0.007054444444444413, 0.13073888888888888, 0.008890000000000002]