SciPy-1-12-中文文档-六十四-

131 阅读54分钟

SciPy 1.12 中文文档(六十四)

原文:docs.scipy.org/doc/scipy-1.12.0/index.html

scipy.stats.mannwhitneyu

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.mannwhitneyu.html#scipy.stats.mannwhitneyu

scipy.stats.mannwhitneyu(x, y, use_continuity=True, alternative='two-sided', axis=0, method='auto', *, nan_policy='propagate', keepdims=False)

对两个独立样本执行曼-惠特尼 U 秩和检验。

曼-惠特尼 U 检验是对假设的非参数检验:样本x的底层分布与样本y的底层分布相同。它通常用作分布之间位置差异的检验。

参数:

x, y数组样本

N 维样本数组。这些数组必须是可广播的,除了给定的axis维度外。

use_continuity布尔值,可选项

是否应用连续性修正(1/2)。当method为'asymptotic'时,默认为 True;否则不起作用。

alternative{‘two-sided’, ‘less’, ‘greater’},可选项

定义备择假设。默认为‘two-sided’。设F(u)G(u)xy的底层分布的累积分布函数,则可用以下备择假设:

  • ‘two-sided’: 分布不相等,即对至少一个uF(u) ≠ G(u)

  • ‘less’: x的分布在随机上小于y的分布,即F(u) > G(u)对于所有u成立。

  • ‘greater’: x的分布在随机上大于y的分布,即F(u) < G(u)对于所有u成立。

注意,上述备择假设中的数学表达式描述了底层分布的累积分布函数(CDF)。不过乍一看,不等式的方向与自然语言描述似乎不一致,但实际上并非如此。例如,假设XY是随机变量,分别服从具有 CDF FG的分布。如果对所有uF(u) > G(u),则从X抽取的样本往往小于从Y抽取的样本。

在更严格的假设集下,备择假设可以根据分布的位置来表达;见[5]第 5.1 节。

axis整数或 None,默认值:0

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

method{‘auto’, ‘asymptotic’, ‘exact’},可选项

选择用于计算p-值的方法。默认为‘auto’。以下选项可用。

  • 'asymptotic': 将标准化的检验统计量与正态分布进行比较,修正并列值。

  • 'exact': 通过将观察到的U统计量与零假设下U统计量的确切分布进行比较,计算确切的p-值。不对并列值进行修正。

  • 'auto': 当一个样本的大小小于或等于 8,并且没有关系时,选择 'exact';否则选择 'asymptotic'

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

定义如何处理输入的 NaN。

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

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

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

keepdimsbool,默认为 False

如果设置为 True,则减少的轴将作为大小为一的维度保留在结果中。使用此选项,结果将正确地与输入数组进行广播。

返回:

resMannwhitneyuResult

包含属性的对象:

statisticfloat

与样本 x 相对应的曼-惠特尼 U 统计量。有关与样本 y 相对应的检验统计量,请参见注释。

pvaluefloat

选择的 alternative 的相关 p-value。

另请参阅

scipy.stats.wilcoxonscipy.stats.ranksumsscipy.stats.ttest_ind

注释

如果 U1 是与样本 x 对应的统计量,则与样本 y 对应的统计量为 U2 = x.shape[axis] * y.shape[axis] - U1

mannwhitneyu 用于独立样本。对于相关/配对样本,请考虑 scipy.stats.wilcoxon

method 'exact' 在没有关系且任一样本大小小于 8 时建议使用[1]。实现遵循原始提议的递归关系[1],如[3]中描述的那样。请注意,确切方法校正关系,但 mannwhitneyu 不会在数据中存在关系时引发错误或警告。

曼-惠特尼 U 检验是独立样本 t 检验的非参数版本。当来自群体的样本的均值正态分布时,请考虑 scipy.stats.ttest_ind

从 SciPy 1.9 开始,np.matrix 输入(不建议新代码使用)在执行计算之前会转换为 np.ndarray。在这种情况下,输出将是适当形状的标量或 np.ndarray,而不是 2D np.matrix。类似地,虽然忽略掩码数组的掩码元素,但输出将是标量或具有 mask=Falsenp.ndarray,而不是掩码数组。

参考文献

[1] (1,2)

H.B. Mann 和 D.R. Whitney, “On a test of whether one of two random variables is stochastically larger than the other”, 数理统计学年报, Vol. 18, pp. 50-60, 1947.

[2]

曼-惠特尼 U 检验, 维基百科, en.wikipedia.org/wiki/Mann-Whitney_U_test

[3]

A. Di Bucchianico, “Combinatorics, computer algebra, and the Wilcoxon-Mann-Whitney test”, 统计规划与推断杂志, Vol. 79, pp. 349-364, 1999.

[4] (1,2,3,4,5,6,7)

Rosie Shier, “Statistics: 2.3 The Mann-Whitney U Test”, 数学学习支持中心, 2004.

[5]

Michael P. Fay 和 Michael A. Proschan。“Wilcoxon-Mann-Whitney or t-test? On assumptions for hypothesis tests and multiple interpretations of decision rules.” 统计调查, Vol. 4, pp. 1-39, 2010. www.ncbi.nlm.nih.gov/pmc/articles/PMC2857732/

例子

我们遵循来自[4]的示例:九名随机抽样的年轻成年人被诊断为二型糖尿病的年龄如下。

>>> males = [19, 22, 16, 29, 24]
>>> females = [20, 11, 17, 12] 

我们使用曼-惠特尼 U 检验来评估男性和女性诊断年龄之间是否存在统计学显著差异。零假设是男性诊断年龄的分布与女性诊断年龄的分布相同。我们决定需要在 95%的置信水平下拒绝零假设,支持分布不同的备择假设。由于样本数非常小且数据中没有并列项,我们可以将观察到的测试统计量与零假设下测试统计量的精确分布进行比较。

>>> from scipy.stats import mannwhitneyu
>>> U1, p = mannwhitneyu(males, females, method="exact")
>>> print(U1)
17.0 

mannwhitneyu 总是报告与第一样本相关的统计量,这在本例中是男性。这与在[4]报告的 (U_M = 17) 一致。第二统计量相关的统计量可以计算:

>>> nx, ny = len(males), len(females)
>>> U2 = nx*ny - U1
>>> print(U2)
3.0 

这与在[4]报告的 (U_F = 3) 一致。双侧p-值可以从任一统计量计算,而由mannwhitneyu产生的值与在[4]报告的 (p = 0.11) 一致。

>>> print(p)
0.1111111111111111 

测试统计量的确切分布渐近正态,因此示例继续通过比较精确的p-值与使用正态近似产生的p-值。

>>> _, pnorm = mannwhitneyu(males, females, method="asymptotic")
>>> print(pnorm)
0.11134688653314041 

在这里,mannwhitneyu 报告的 p-值似乎与 [4] 给出的值 (p = 0.09) 存在冲突。原因是 [4] 没有应用由 mannwhitneyu 执行的连续性校正;mannwhitneyu 减少了测试统计量与均值 (\mu = n_x n_y / 2) 之间的距离 0.5,以校正离散统计量与连续分布的比较。在这里,使用的 (U) 统计量小于均值,因此我们在分子中加入了 0.5 以减少距离。

>>> import numpy as np
>>> from scipy.stats import norm
>>> U = min(U1, U2)
>>> N = nx + ny
>>> z = (U - nx*ny/2 + 0.5) / np.sqrt(nx*ny * (N + 1)/ 12)
>>> p = 2 * norm.cdf(z)  # use CDF to get p-value from smaller statistic
>>> print(p)
0.11134688653314041 

如果需要,我们可以禁用连续性校正,以获得与 [4] 报告的结果一致的结果。

>>> _, pnorm = mannwhitneyu(males, females, use_continuity=False,
...                         method="asymptotic")
>>> print(pnorm)
0.0864107329737 

无论我们执行精确还是渐近检验,测试统计量出现这样或更极端的概率超过 5%,因此我们不认为结果具有统计学意义。

假设在查看数据之前,我们假设女性被诊断的年龄比男性更年轻。在这种情况下,将女性年龄作为第一个输入是很自然的选择,我们将使用alternative = 'less'执行单侧检验:女性被诊断的年龄随机地小于男性。

>>> res = mannwhitneyu(females, males, alternative="less", method="exact")
>>> print(res)
MannwhitneyuResult(statistic=3.0, pvalue=0.05555555555555555) 

再次强调,在零假设下,测试统计量得到足够低的概率大于 5%,因此我们不拒绝零假设,支持我们的备择假设。

如果合理假设来自两个总体样本的均值是正态分布的,我们可以使用 t 检验进行分析。

>>> from scipy.stats import ttest_ind
>>> res = ttest_ind(females, males, alternative="less")
>>> print(res)
Ttest_indResult(statistic=-2.239334696520584, pvalue=0.030068441095757924) 

在这种假设下,p-值足够低,可以拒绝零假设,支持备择假设。

scipy.stats.bws_test

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.bws_test.html#scipy.stats.bws_test

scipy.stats.bws_test(x, y, *, alternative='two-sided', method=None)

对两个独立样本执行 Baumgartner-Weiss-Schindler 测试。

Baumgartner-Weiss-Schindler(BWS)测试是对零假设进行非参数检验,即样本x背后的分布与样本y背后的分布相同。与 Kolmogorov-Smirnov、Wilcoxon 和 Cramer-Von Mises 测试不同,BWS 测试通过差异累积分布函数(CDFs)的方差加权积分,强调分布的尾部,从而提高了许多应用中的检验能力。

参数:

x, yarray-like

1-d arrays of samples.

alternative{‘two-sided’, ‘less’, ‘greater’}, optional

定义备择假设。默认为‘two-sided’。设F(u)G(u)xy背后的分布的累积分布函数,则以下备择假设可用:

  • ‘two-sided’:分布不相等,即至少存在一个u使得F(u) ≠ G(u)

  • ‘less’:x背后的分布小于y背后的分布,即F(u) >= G(u)对于所有u

  • ‘greater’:x背后的分布大于y背后的分布,即F(u) <= G(u)对于所有u

在更严格的假设集下,备择假设可以用分布的位置表示;参见[2]第 5.1 节。

methodPermutationMethod, optional

配置用于计算 p 值的方法。默认是默认的PermutationMethod对象。

返回:

resPermutationTestResult

具有以下属性的对象:

statisticfloat

数据的观察检验统计量。

pvaluefloat

给定备择假设的 p 值。

null_distributionndarray

在零假设下生成的检验统计量的值。

另见

scipy.stats.wilcoxon, scipy.stats.mannwhitneyu, scipy.stats.ttest_ind

注:

alternative=='two-sided'时,统计量由[1]第二部分中给出的方程定义。该统计量不适用于单侧备择假设;在这种情况下,统计量为[1]第二部分中给出的方程的负值。因此,当第一个样本的分布大于第二个样本的分布时,统计量趋向于为正。

参考文献

[1] (1,2,3,4,5)

Neuhäuser, M. (2005). Baumgartner-Weiss-Schindler 统计量的精确检验:一项调查。Statistical Papers, 46(1), 1-29。

[2]

Fay, M. P., & Proschan, M. A. (2010). Wilcoxon-Mann-Whitney 还是 t 检验?关于假设检验的假设和决策规则的多重解释。Statistics Surveys, 4, 1。

例如

我们遵循[1]中表 3 的示例:十四名儿童随机分为两组。他们在进行特定测试时的排名如下。

>>> import numpy as np
>>> x = [1, 2, 3, 4, 6, 7, 8]
>>> y = [5, 9, 10, 11, 12, 13, 14] 

我们使用 BWS 测试来评估两组之间是否存在统计显著差异。零假设是两组表现分布没有差异。我们决定以 1%的显著水平拒绝零假设,支持备择假设,即两组表现分布不同。由于样本量非常小,我们可以将观察到的检验统计量与在零假设下检验统计量的精确分布进行比较。

>>> from scipy.stats import bws_test
>>> res = bws_test(x, y)
>>> print(res.statistic)
5.132167152575315 

这与在[1]中报告的( B = 5.132 )一致。由bws_test产生的p-值也与在[1]中报告的( p = 0.0029 )一致。

>>> print(res.pvalue)
0.002913752913752914 

因为 p 值低于我们的 1%阈值,我们将其视为反对零假设的证据,支持备择假设,即两组表现存在差异。

scipy.stats.ranksums

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.ranksums.html#scipy.stats.ranksums

scipy.stats.ranksums(x, y, alternative='two-sided', *, axis=0, nan_policy='propagate', keepdims=False)

计算两个样本的 Wilcoxon 秩和统计量。

Wilcoxon 秩和检验用于检验两组测量是否来自同一分布的零假设。备择假设是一个样本中的值更可能比另一个样本中的值大。

该检验用于比较来自连续分布的两个样本。不处理 xy 中测量之间的并列。有关并列处理和可选连续性修正,请参阅 scipy.stats.mannwhitneyu

参数:

x,yarray_like

来自两个样本的数据。

alternative{‘two-sided’, ‘less’, ‘greater’}, 可选

定义备择假设。默认为 ‘two-sided’。可用选项如下:

  • ‘two-sided’: xy 中的一个分布大于另一个分布。

  • ‘less’: 代表 x 分布的概率小于 y 分布的概率。

  • ‘greater’: 代表 x 分布的概率大于 y 分布的概率。

自版本 1.7.0 开始新增。

axisint 或 None,默认值为 0

如果是整数,则是输入的轴,沿着该轴计算统计量。输入的每个轴切片(例如行)的统计量将显示在输出的相应元素中。如果为 None,则在计算统计量之前将展平输入。

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

定义如何处理输入 NaN。

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

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

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

keepdimsbool,默认值为 False

如果设置为 True,则会将减少的轴保留在结果中,作为大小为一的维度。使用此选项,结果将正确广播到输入数组。

返回:

statisticfloat

在大样本近似下,秩和统计量被正态分布所取代的检验统计量。

pvaluefloat

检验的 p 值。

注意事项

自 SciPy 1.9 开始,np.matrix 输入(不建议新代码使用)在执行计算之前将转换为 np.ndarray。在这种情况下,输出将是适当形状的标量或 np.ndarray,而不是 2D 的 np.matrix。类似地,虽然忽略掩码数组的屏蔽元素,但输出将是标量或 np.ndarray,而不是具有 mask=False 的掩码数组。

参考文献

[1]

威尔科克森秩和检验

示例

我们可以通过计算威尔科克森秩和统计量来检验两个独立的不等大小样本是否来自同一分布。

>>> import numpy as np
>>> from scipy.stats import ranksums
>>> rng = np.random.default_rng()
>>> sample1 = rng.uniform(-1, 1, 200)
>>> sample2 = rng.uniform(-0.5, 1.5, 300) # a shifted distribution
>>> ranksums(sample1, sample2)
RanksumsResult(statistic=-7.887059,
 pvalue=3.09390448e-15) # may vary
>>> ranksums(sample1, sample2, alternative='less')
RanksumsResult(statistic=-7.750585297581713,
 pvalue=4.573497606342543e-15) # may vary
>>> ranksums(sample1, sample2, alternative='greater')
RanksumsResult(statistic=-7.750585297581713,
 pvalue=0.9999999999999954) # may vary 

p 值小于0.05表明在 5%的显著性水平下,该检验拒绝了假设。

scipy.stats.brunnermunzel

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.brunnermunzel.html#scipy.stats.brunnermunzel

scipy.stats.brunnermunzel(x, y, alternative='two-sided', distribution='t', nan_policy='propagate')

计算样本 x 和 y 上的 Brunner-Munzel 检验。

Brunner-Munzel 检验是一个非参数检验,用于检验以下原假设:当从每个组中逐个取值时,两组中获得大值的概率相等。与 Wilcoxon-Mann-Whitney U 检验不同,这不要求两组方差相同。注意,这并不假设分布相同。此检验适用于两个独立样本,可能大小不同。

参数:

x, yarray_like

样本数组,应为一维。

alternative{‘two-sided’, ‘less’, ‘greater’},可选

定义备择假设。以下选项可用(默认为'双边'):

  • ‘two-sided’
  • ‘less’:单侧
  • ‘greater’:单侧

distribution{‘t’, ‘normal’},可选

定义如何获取 p 值。以下选项可用(默认为‘t’):

  • ‘t’:通过 t 分布获取 p 值
  • ‘normal’:通过标准正态分布获取 p 值。

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

定义如何处理输入包含 NaN 时的情况。以下选项可用(默认为‘propagate’):

  • ‘propagate’:返回 NaN
  • ‘raise’:抛出错误
  • ‘omit’:在计算中忽略 NaN 值

返回:

statisticfloat

Brunner-Munzel 检验的 W 统计量。

pvaluefloat

假设 t 分布的 p 值。单侧或双侧,取决于 alternativedistribution 的选择。

另请参阅

mannwhitneyu

两个样本的 Mann-Whitney 秩和检验。

注释

当数据大小为 50 或更小时,Brunner 和 Munzel 建议使用 t 分布来估计 p 值。如果大小小于 10,则最好使用置换 Brunner Munzel 检验(参见[2])。

参考文献

[1]

Brunner, E. 和 Munzel, U. “非参数 Benhrens-Fisher 问题:渐近理论和小样本近似”。生物统计学期刊。Vol. 42(2000): 17-25。

[2]

Neubert, K. 和 Brunner, E. “非参数 Behrens-Fisher 问题的学生化置换检验”。计算统计与数据分析。Vol. 51(2007): 5192-5204。

示例

>>> from scipy import stats
>>> x1 = [1,2,1,1,1,1,1,1,1,1,2,4,1,1]
>>> x2 = [3,3,4,3,1,2,3,1,1,5,4]
>>> w, p_value = stats.brunnermunzel(x1, x2)
>>> w
3.1374674823029505
>>> p_value
0.0057862086661515377 

scipy.stats.mood

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.mood.html#scipy.stats.mood

scipy.stats.mood(x, y, axis=0, alternative='two-sided')

执行 Mood 的等标尺参数检验。

Mood 双样本标尺参数检验是针对两个样本是否来自具有相同标尺参数的相同分布的零假设的非参数检验。

参数:

x, yarray_like

样本数据的数组。

axisint,可选

在进行测试的轴线。xy 可以沿着 axis 有不同长度。如果 axis 是 None,则 xy 被展平,并且在展平的数组中进行测试。

alternative{‘two-sided’, ‘less’, ‘greater’},可选

定义备择假设。默认为 'two-sided'。以下选项可用:

  • ‘two-sided’:xy 下 lying 分布的标尺不同。

  • ‘less’:x 下 lying 分布的标尺小于 y 下 lying 分布的标尺。

  • ‘greater’:x 下 lying 分布的标尺大于 y 下 lying 分布的标尺。

新版本 1.7.0 中引入。

返回:

resSignificanceResult

包含以下属性的对象:

statisticscalar 或 ndarray

假设检验的 z 分数。对于一维输入,返回标量。

pvaluescalar ndarray

假设检验的 p 值。

另请参阅

fligner

k 个方差相等的非参数检验

ansari

两个方差相等的非参数检验

bartlett

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

levene

k 个方差相等的参数检验

注释

假设数据分别从概率分布 f(x)f(x/s) / s 中提取,其中 f 是某个概率密度函数。零假设是 s == 1

对于多维数组,如果输入的形状为 (n0, n1, n2, n3)(n0, m1, n2, n3),则如果 axis=1,则得到的 z 值和 p 值的形状将为 (n0, n2, n3)。注意 n1m1 不必相等,但其他维度必须相等。

参考文献

[1] Mielke, Paul W. “Note on Some Squared Rank Tests with Existing Ties.”

Technometrics,第 9 卷,第 2 期,1967 年,第 312-14 页。JSTOR,doi.org/10.2307/1266427。访问于 2022 年 5 月 18 日。

示例

>>> import numpy as np
>>> from scipy import stats
>>> rng = np.random.default_rng()
>>> x2 = rng.standard_normal((2, 45, 6, 7))
>>> x1 = rng.standard_normal((2, 30, 6, 7))
>>> res = stats.mood(x1, x2, axis=1)
>>> res.pvalue.shape
(2, 6, 7) 

查找标尺差异不显著的点数:

>>> (res.pvalue > 0.1).sum()
78 

以不同标尺执行测试:

>>> x1 = rng.standard_normal((2, 30))
>>> x2 = rng.standard_normal((2, 35)) * 10.0
>>> stats.mood(x1, x2, axis=1)
SignificanceResult(statistic=array([-5.76174136, -6.12650783]),
 pvalue=array([8.32505043e-09, 8.98287869e-10])) 

scipy.stats.ansari

原始文档:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.ansari.html#scipy.stats.ansari

scipy.stats.ansari(x, y, alternative='two-sided', *, axis=0, nan_policy='propagate', keepdims=False)

执行 Ansari-Bradley 检验以确定尺度参数是否相等。

Ansari-Bradley 检验([1][2])是检验从两个样本抽取的分布的尺度参数相等性的非参数检验。原假设表明,x的分布的尺度与y的分布的尺度的比值为 1。

参数:

x, yarray_like

样本数据数组。

alternative{‘two-sided’, ‘less’, ‘greater’},可选

定义备择假设。默认为‘two-sided’。可用的选项如下:

  • ‘two-sided’: 比例尺不等于 1。

  • ‘less’: 比例尺小于 1。

  • ‘greater’: 比例尺大于 1。

自 1.7.0 版本新增。

axisint 或 None,默认值:0

如果为整数,则输入的轴沿着计算统计量。输入的每个轴切片(例如行)的统计量将出现在输出的对应元素中。如果为None,则在计算统计量之前将对输入进行展平。

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

定义如何处理输入中的 NaN。

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

  • omit: 在执行计算时将省略 NaN。如果轴切片中剩余的数据不足以进行统计计算,则对应的输出将是 NaN。

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

keepdimsbool,默认值:False

如果设置为 True,则会将被减少的轴保留在结果中作为大小为 1 的维度。使用此选项,结果将正确传播到输入数组。

返回:

statisticfloat

Ansari-Bradley 检验统计量。

pvaluefloat

假设检验的 p 值。

另请参阅

fligner

用于检验 k 个方差的非参数检验

mood

用于比较两个尺度参数的非参数检验

注意事项

当样本大小都小于 55 且没有任何平局时,给定的 p 值是精确的;否则,将使用 p 值的正态近似值。

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

参考文献

[1]

Ansari, A. R.和 Bradley, R. A.(1960)Dispersion 的秩和检验,数理统计学年鉴,31,1174-1189。

[2]

Sprent, Peter 和 N.C. Smeeton。应用非参数统计方法。第三版。Chapman and Hall/CRC。2001 年。第 5.8.2 节。

[3]

Nathaniel E. Helwig 的“非参数分散和平等性检验”在users.stat.umn.edu/~helwig/notes/npde-Notes.pdf

例子

>>> import numpy as np
>>> from scipy.stats import ansari
>>> rng = np.random.default_rng() 

对于这些示例,我们将创建三个随机数据集。前两个大小分别为 35 和 25,从均值为 0、标准差为 2 的正态分布中抽取。第三个数据集大小为 25,从标准差为 1.25 的正态分布中抽取。

>>> x1 = rng.normal(loc=0, scale=2, size=35)
>>> x2 = rng.normal(loc=0, scale=2, size=25)
>>> x3 = rng.normal(loc=0, scale=1.25, size=25) 

首先我们对x1x2应用ansari。这些样本来自同一分布,因此我们预计 Ansari-Bradley 检验不会导致我们得出分布比例不同的结论。

>>> ansari(x1, x2)
AnsariResult(statistic=541.0, pvalue=0.9762532927399098) 

由于 p 值接近 1,我们不能断定在比例上存在显著差异(符合预期)。

现在将测试应用于x1x3

>>> ansari(x1, x3)
AnsariResult(statistic=425.0, pvalue=0.0003087020407974518) 

在零假设相等的情况下观察到统计量极端值的概率仅为 0.03087%。我们将其视为支持备择假设的证据:从样本中抽取的分布的比例不相等。

我们可以使用alternative参数执行单侧检验。在上述示例中,x1的比例大于x3,因此x1x3的比例大于 1。这意味着当alternative='greater'时,p 值应接近 0,因此我们应该能够拒绝零假设:

>>> ansari(x1, x3, alternative='greater')
AnsariResult(statistic=425.0, pvalue=0.0001543510203987259) 

正如我们所见,p 值确实非常低。因此,使用alternative='less'应该产生较大的 p 值:

>>> ansari(x1, x3, alternative='less')
AnsariResult(statistic=425.0, pvalue=0.9998643258449039) 

scipy.stats.cramervonmises_2samp

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.cramervonmises_2samp.html#scipy.stats.cramervonmises_2samp

scipy.stats.cramervonmises_2samp(x, y, method='auto', *, axis=0, nan_policy='propagate', keepdims=False)

执行双样本 Cramér-von Mises 拟合优度检验。

这是 Cramér-von Mises 双样本检验的版本(1):对于两个独立样本 (X_1, ..., X_n) 和 (Y_1, ..., Y_m),原假设是这些样本来自相同(未指定的)连续分布。

参数:

xarray_like

1-D 数组,观测到的随机变量 (X_i) 的值。

yarray_like

1-D 数组,观测到的随机变量 (Y_i) 的值。

method{‘auto’, ‘asymptotic’, ‘exact’},可选

用于计算 p 值的方法,请参见注意事项了解详情。默认为 ‘auto’。

axisint 或 None,默认值:0

如果是整数,则为输入的轴,沿其计算统计量。输入的每个轴切片(例如行)的统计量将显示在输出的相应元素中。如果为 None,则在计算统计量之前将对输入进行拉平。

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

定义如何处理输入的 NaN 值。

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

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

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

keepdimsbool,默认值:False

如果设置为 True,则减少的轴将作为大小为一的维度保留在结果中。通过这个选项,结果将正确地与输入数组进行广播。

返回:

res具有属性的对象

statisticfloat

Cramér-von Mises 统计量。

pvaluefloat

p 值。

参见

cramervonmisesanderson_ksampepps_singleton_2sampks_2samp

注意事项

新版本 1.7.0 中引入。

根据 2 中的方程式 9 计算统计量。p 值的计算取决于关键字 method

  • asymptotic:通过使用检验统计量的极限分布来近似 p 值。

  • exact:通过枚举测试统计量的所有可能组合来计算精确的 p 值,参见 2。

如果 method='auto',则在两个样本包含等于或少于 20 个观测值时使用精确方法,否则使用渐近分布。

如果基础分布不是连续的,则 p 值可能是保守的(第 6.2 节在[3])。在计算检验统计量时,如果存在并列,则使用中位秩。

从 SciPy 1.9 开始,np.matrix 输入(不推荐新代码使用)在执行计算之前会转换为 np.ndarray。在这种情况下,输出将是一个相应形状的标量或 np.ndarray,而不是二维 np.matrix。类似地,虽然忽略了遮罩数组的遮罩元素,但输出将是一个标量或 np.ndarray,而不是具有 mask=False 的遮罩数组。

参考文献

[1]

en.wikipedia.org/wiki/Cramer-von_Mises_criterion

[2] (1,2)

Anderson, T.W. (1962). On the distribution of the two-sample Cramer-von-Mises criterion. The Annals of Mathematical Statistics, pp. 1148-1159.

[3]

Conover, W.J., Practical Nonparametric Statistics, 1971.

示例

假设我们希望测试由 scipy.stats.norm.rvs 生成的两个样本是否具有相同分布。我们选择显著性水平 alpha=0.05。

>>> import numpy as np
>>> from scipy import stats
>>> rng = np.random.default_rng()
>>> x = stats.norm.rvs(size=100, random_state=rng)
>>> y = stats.norm.rvs(size=70, random_state=rng)
>>> res = stats.cramervonmises_2samp(x, y)
>>> res.statistic, res.pvalue
(0.29376470588235293, 0.1412873014573014) 

p 值超过了我们选择的显著性水平,因此我们不拒绝观察到的样本来自相同分布的原假设。

对于小样本量,可以计算精确的 p 值:

>>> x = stats.norm.rvs(size=7, random_state=rng)
>>> y = stats.t.rvs(df=2, size=6, random_state=rng)
>>> res = stats.cramervonmises_2samp(x, y, method='exact')
>>> res.statistic, res.pvalue
(0.197802197802198, 0.31643356643356646) 

基于渐近分布的 p 值是一个良好的近似,即使样本量很小。

>>> res = stats.cramervonmises_2samp(x, y, method='asymptotic')
>>> res.statistic, res.pvalue
(0.197802197802198, 0.2966041181527128) 

无论方法如何,在此示例中选择的显著性水平下,均无法拒绝原假设。

scipy.stats.epps_singleton_2samp

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.epps_singleton_2samp.html#scipy.stats.epps_singleton_2samp

scipy.stats.epps_singleton_2samp(x, y, t=(0.4, 0.8), *, axis=0, nan_policy='propagate', keepdims=False)

计算 Epps-Singleton(ES)测试统计量。

检验两个样本是否具有相同的概率分布的零假设。

参数:

x, y类似数组

要测试的两个观测样本。输入不能有多个维度。样本可以有不同的长度。

t类似数组,可选

要评估经验特征函数的点(t1, …, tn)。它应该是正的不同的数。默认值(0.4, 0.8)建议在[1]中。输入不能有多个维度。

axis整数或 None,默认:0

如果是整数,则是计算统计量时输入的轴。输入的每个轴切片(例如行)的统计量将出现在输出的相应元素中。如果None,则在计算统计量之前将对输入进行拉平处理。

nan_policy{‘传播’, ‘省略’, ‘提升’}

定义如何处理输入的 NaN。

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

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

  • raise:如果存在 NaN,则会引发ValueError异常。

keepdims布尔值,默认:False

如果设置为 True,则减少的轴将保留为大小为一的维度结果中。使用此选项,结果将正确广播到输入数组。

返回:

statistic浮点数

测试统计量。

pvalue浮点数

基于渐近 chi2 分布的相关 p 值。

另请参见

ks_2samp, anderson_ksamp

注意事项

在统计学中,测试两个样本是否由相同的基础分布生成是一个经典问题。广泛使用的测试是基于经验分布函数的 Kolmogorov-Smirnov(KS)测试。Epps 和 Singleton 引入了基于经验特征函数的测试[1]

与 KS 检验相比,ES 检验的一个优势是不假设连续分布。在 [1] 中,作者得出结论,该检验在许多示例中的功效也高于 KS 检验。他们建议不仅对离散样本使用 ES 检验,还建议对每个至少有 25 个观察值的连续样本使用,而对于连续情况下较小的样本量,则推荐使用 anderson_ksamp

p 值是从检验统计量的渐近分布计算得出的,该分布遵循一个 chi2 分布。如果 xy 的样本量都小于 25,那么将应用于检验统计量的小样本修正,该修正在 [1] 中提出。

t 的默认值是在 [1] 中通过考虑各种分布来确定的,并找到导致一般情况下检验功效高的良好值。在 [1] 中的表 III 给出了在该研究中测试的分布的最优值。在实现中,t 的值由半分位间距进行缩放,请参阅 [1]

从 SciPy 1.9 开始,np.matrix 输入(不建议新代码使用)在进行计算之前会被转换为 np.ndarray。在这种情况下,输出将是一个适当形状的标量或 np.ndarray,而不是二维 np.matrix。同样地,虽然忽略了掩码数组的掩码元素,但输出将是一个标量或 np.ndarray,而不是带有 mask=False 的掩码数组。

参考文献

[1] (1,2,3,4,5,6,7)

T. W. Epps 和 K. J. Singleton,“使用经验特征函数的两样本问题的综合检验”,Journal of Statistical Computation and Simulation 26,第 177–203 页,1986 年。

[2]

S. J. Goerg 和 J. Kaiser,“使用经验特征函数进行分布的非参数检验 - Epps-Singleton 两样本检验”,Stata Journal 9(3),第 454–465 页,2009 年。

scipy.stats.ks_2samp

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.ks_2samp.html#scipy.stats.ks_2samp

scipy.stats.ks_2samp(data1, data2, alternative='two-sided', method='auto', *, axis=0, nan_policy='propagate', keepdims=False)

执行两样本 Kolmogorov-Smirnov 拟合优度检验。

此检验比较两个独立样本的底层连续分布 F(x) 和 G(x)。请参阅注释以了解可用的零假设和备择假设描述。

参数:

data1, data2array_like,1 维

假设两个样本观察结果数组来自连续分布,样本大小可能不同。

alternative{‘two-sided’, ‘less’, ‘greater’},可选

定义零假设和备择假设。默认为 ‘two-sided’。请参阅下方注释中的解释。

method{‘auto’, ‘exact’, ‘asymp’},可选

定义了计算 p 值所用的方法。以下选项可供选择(默认为 ‘auto’):

  • ‘auto’:对于小数组大小使用 ‘exact’,对于大数组使用 ‘asymp’
  • ‘exact’:使用检验统计量的确切分布
  • ‘asymp’:使用检验统计量的渐近分布

axisint 或 None,默认为 0

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

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

定义如何处理输入的 NaN 值。

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

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

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

keepdimsbool,默认为 False

如果设置为 True,则会将被减少的轴保留在结果中作为尺寸为一的维度。使用此选项,结果将正确传播至输入数组。

返回:

res:KstestResult

一个包含属性的对象:

statisticfloat

KS 检验统计量。

pvaluefloat

单尾或双尾 p 值。

statistic_locationfloat

来自 data1data2 与 KS 统计量对应的值;即,在此观察值处度量经验分布函数之间的距离。

statistic_signint

如果 data1 的经验分布函数在 statistic_location 处超过 data2 的经验分布函数,则为 +1,否则为 -1。

另请参见

kstest, ks_1samp, epps_singleton_2samp, anderson_ksamp

注意

可以使用alternative参数选择三种零假设及其对应的备择假设。

  • less: 零假设是对于所有的 x,F(x) >= G(x);备择假设是至少有一个 x 使得 F(x) < G(x)。统计量是样本的经验分布函数之间最小(最负)差异的大小。

  • greater: 零假设是对于所有的 x,F(x) <= G(x);备择假设是至少有一个 x 使得 F(x) > G(x)。统计量是样本的经验分布函数之间的最大(最正)差异。

  • two-sided: 零假设是两个分布是相同的,即对于所有的 x,F(x)=G(x);备择假设是它们不相同。统计量是样本的经验分布函数之间的最大绝对差异。

注意备择假设描述了基础分布的CDFs,而不是数据的观察值。例如,假设 x1 ~ F 和 x2 ~ G。如果对于所有的 x,F(x) > G(x),则 x1 中的值倾向于小于 x2 中的值。

如果 KS 统计量很大,则 p 值很小,这可能表明零假设被否定,支持备择假设。

如果method='exact'ks_2samp 试图计算一个精确的 p 值,即在零假设下获得与从数据计算出的测试统计值一样极端的概率。如果method='asymp',则使用渐近的 Kolmogorov-Smirnov 分布来计算近似 p 值。如果method='auto',则如果两个样本量均小于 10000,则尝试精确 p 值计算;否则,使用渐近方法。无论如何,如果尝试并失败了精确 p 值计算,将发出警告,并返回渐近 p 值。

‘two-sided’ ‘exact’ 计算计算补充概率,然后从 1 中减去。因此,它能返回的最小概率约为 1e-16。虽然算法本身是精确的,但对于大样本量,数值误差可能会累积。它最适用于其中一个样本量仅为几千的情况。

我们通常遵循 Hodges 对 Drion/Gnedenko/Korolyuk 的处理[1]

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

参考文献

[1]

Hodges, J.L. Jr., “斯米尔诺夫双样本检验的显著性概率”,《数学档案》,3,No. 43(1958),469-486。

示例

假设我们希望检验两个样本是否来自同一分布的零假设。我们选择 95% 的置信水平;也就是说,如果 p 值小于 0.05,我们将拒绝零假设,支持备选假设。

如果第一个样本是从均匀分布抽取的,而第二个样本是从标准正态分布抽取的,我们预期将拒绝零假设。

>>> import numpy as np
>>> from scipy import stats
>>> rng = np.random.default_rng()
>>> sample1 = stats.uniform.rvs(size=100, random_state=rng)
>>> sample2 = stats.norm.rvs(size=110, random_state=rng)
>>> stats.ks_2samp(sample1, sample2)
KstestResult(statistic=0.5454545454545454, pvalue=7.37417839555191e-15) 

实际上,p 值低于我们的阈值 0.05,因此我们拒绝零假设,支持“双边”替代假设:数据不是来自同一分布。

当两个样本来自相同分布时,我们期望数据大部分时间与零假设一致。

>>> sample1 = stats.norm.rvs(size=105, random_state=rng)
>>> sample2 = stats.norm.rvs(size=95, random_state=rng)
>>> stats.ks_2samp(sample1, sample2)
KstestResult(statistic=0.10927318295739348, pvalue=0.5438289009927495) 

正如预期的那样,p 值为 0.54 不低于我们的阈值 0.05,因此我们无法拒绝零假设。

然而,假设第一个样本是从向更大值偏移的正态分布中抽取的。在这种情况下,底层分布的累积密度函数(CDF)倾向于小于第二个样本的 CDF。因此,我们预计将拒绝零假设,采用alternative='less'

>>> sample1 = stats.norm.rvs(size=105, loc=0.5, random_state=rng)
>>> stats.ks_2samp(sample1, sample2, alternative='less')
KstestResult(statistic=0.4055137844611529, pvalue=3.5474563068855554e-08) 

而且,确实,p 值小于我们的阈值,我们拒绝零假设,支持备选假设。

scipy.stats.kstest

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.kstest.html#scipy.stats.kstest

scipy.stats.kstest(rvs, cdf, args=(), N=20, alternative='two-sided', method='auto', *, axis=0, nan_policy='propagate', keepdims=False)

执行(单样本或双样本)Kolmogorov-Smirnov 拟合优度检验。

单样本检验将样本的底层分布 F(x)与给定分布 G(x)进行比较。双样本检验比较两个独立样本的底层分布。这两个检验仅适用于连续分布。

参数:

rvs字符串、array_like 或可调用对象

如果是数组,则应该是随机变量观测的 1-D 数组。如果是可调用对象,则应该是生成随机变量的函数;它需要一个关键字参数size。如果是字符串,则应该是scipy.stats中分布的名称,将用于生成随机变量。

cdf字符串、array_like 或可调用对象

如果 array_like,则应该是随机变量观测的 1-D 数组,并执行双样本检验(rvs 必须是 array_like)。如果是可调用对象,则使用该可调用对象计算 cdf。如果是字符串,则应该是scipy.stats中分布的名称,将用作 cdf 函数。

args元组、序列,可选

分布参数,如果rvscdf是字符串或可调用对象。

N整数,可选

如果rvs为字符串或可调用对象,则为样本大小。默认值为 20。

alternative{‘two-sided’, ‘less’, ‘greater’},可选

定义零假设和备择假设。默认为‘two-sided’。请参见下面的说明。

method{‘auto’, ‘exact’, ‘approx’, ‘asymp’},可选

定义用于计算 p 值的分布。提供以下选项(默认为‘auto’):

  • ‘auto’:选择其他选项之一。
  • ‘exact’:使用测试统计量的精确分布。
  • ‘approx’:用两倍的单侧概率近似计算双侧概率
  • ‘asymp’:使用测试统计量的渐近分布

axisint 或 None,默认为 0

如果是 int,则是沿着其计算统计量的输入轴(例如行)的轴。输入的每个轴切片(例如行)的统计量将显示在输出的相应元素中。如果为None,则在计算统计量之前将对输入进行拉平。

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

定义如何处理输入的 NaN。

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

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

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

keepdims布尔值,默认为 False

如果设置为 True,则被减少的轴将保留在结果中作为大小为一的维度。使用此选项,结果将正确地广播到输入数组。

返回:

res:KstestResult

一个包含属性的对象:

统计量浮点数

KS 检验统计量,可以是 D+、D-或者两者中的最大值。

p 值浮点数

单侧或双侧 p 值。

statistic_location 浮点数

在单样本检验中,这是与 KS 统计量对应的rvs的值;即,在这个观察点上测量经验分布函数与假设的累积分布函数之间的距离。

在双样本检验中,这是与 KS 统计量对应的rvscdf的值;即,在这个观察值上测量经验分布函数之间的距离。

statistic_signint

在单样本检验中,如果 KS 统计量是经验分布函数与假设的累积分布函数之间的最大正差异(D+),则此值为+1;如果 KS 统计量是最大负差异(D-),则此值为-1。

在双样本检验中,如果rvs的经验分布函数在statistic_location处超过cdf的经验分布函数,则为+1;否则为-1。

另见

ks_1samp, ks_2samp

可以使用alternative参数选择三种零假设及相应的备择假设。

  • 双边检验:零假设是两个分布在所有点上相同,即 F(x)=G(x);备择假设是它们不相同。

  • 小于:零假设是对所有 x,F(x) >= G(x);备择假设是对至少一个 x,F(x) < G(x)。

  • 大于:零假设是对所有 x,F(x) <= G(x);备择假设是对至少一个 x,F(x) > G(x)。

注意备择假设描述的是底层分布的CDFs,而不是观察值。例如,假设 x1 服从 F,x2 服从 G。如果对所有 x,F(x) > G(x),则 x1 中的值倾向于小于 x2 中的值。

从 SciPy 1.9 开始,不推荐新代码使用np.matrix输入,在计算之前会被转换为np.ndarray。在这种情况下,输出将是一个适当形状的标量或np.ndarray,而不是 2D 的np.matrix。类似地,虽然被屏蔽的数组元素会被忽略,但输出将是一个标量或np.ndarray,而不是带有mask=False的屏蔽数组。

示例

假设我们希望检验样本是否按标准正态分布,我们选择 95%的置信水平;也就是说,如果 p 值小于 0.05,我们将拒绝零假设,支持备择假设。

在测试均匀分布数据时,我们预期将拒绝零假设。

>>> import numpy as np
>>> from scipy import stats
>>> rng = np.random.default_rng()
>>> stats.kstest(stats.uniform.rvs(size=100, random_state=rng),
...              stats.norm.cdf)
KstestResult(statistic=0.5001899973268688, pvalue=1.1616392184763533e-23) 

的确,p 值低于我们的 0.05 阈值,因此我们拒绝零假设,支持默认的“双边”备择假设:数据按标准正态分布分布。

在测试来自标准正态分布的随机变量时,我们预期大部分时间数据与零假设一致。

>>> x = stats.norm.rvs(size=100, random_state=rng)
>>> stats.kstest(x, stats.norm.cdf)
KstestResult(statistic=0.05345882212970396, pvalue=0.9227159037744717) 

如预期,p 值为 0.92 不低于我们的 0.05 阈值,因此我们不能拒绝零假设。

然而,假设随机变量按向更大值偏移的正态分布分布。在这种情况下,基础分布的累积密度函数(CDF)倾向于小于标准正态分布的 CDF。因此,我们期望零假设在alternative='less'时被拒绝:

>>> x = stats.norm.rvs(size=100, loc=0.5, random_state=rng)
>>> stats.kstest(x, stats.norm.cdf, alternative='less')
KstestResult(statistic=0.17482387821055168, pvalue=0.001913921057766743) 

并且,由于 p 值小于我们的阈值,我们拒绝零假设,支持备择假设。

为了方便起见,可以使用分布名称作为第二个参数执行先前的测试。

>>> stats.kstest(x, "norm", alternative='less')
KstestResult(statistic=0.17482387821055168, pvalue=0.001913921057766743) 

上述示例都是与ks_1samp执行的单样本测试相同的。请注意kstest也可以执行与ks_2samp相同的双样本测试。例如,当两个样本来自相同分布时,我们预期大部分时间数据与零假设一致。

>>> sample1 = stats.laplace.rvs(size=105, random_state=rng)
>>> sample2 = stats.laplace.rvs(size=95, random_state=rng)
>>> stats.kstest(sample1, sample2)
KstestResult(statistic=0.11779448621553884, pvalue=0.4494256912629795) 

如预期,p 值为 0.45 不低于我们的 0.05 阈值,因此我们不能拒绝零假设。

scipy.stats.f_oneway

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.f_oneway.html#scipy.stats.f_oneway

scipy.stats.f_oneway(*samples, axis=0)

进行单因素方差分析。

单因素方差分析检验零假设是两个或多个组具有相同的总体均值。该检验适用于来自两个或多个组的样本,可能大小不同。

参数:

**sample1, sample2, …**array_like

每组的样本测量值。必须至少有两个参数。如果数组是多维的,则除了 axis 外,数组的所有维度必须相同。

axisint,可选

应用检验的输入数组的轴。默认为 0。

返回:

statisticfloat

测试的计算 F 统计量。

pvaluefloat

来自 F 分布的相关 p 值。

警告:

ConstantInputWarning

如果所有输入数组中的每个值都相同,则会引发错误。在这种情况下,F 统计量要么是无穷大,要么未定义,因此返回 np.infnp.nan

DegenerateDataWarning

如果任何输入数组的长度为 0,或者所有输入数组的长度为 1,则会引发错误。在这些情况下,返回 np.nan 的 F 统计量和 p 值。

注意事项

方差分析检验有重要的假设条件,这些条件必须满足才能使相关的 p 值有效。

  1. 样本是独立的。

  2. 每个样本都来自一个正态分布的总体。

  3. 所有组的总体标准差相等。这种特性称为等方差性。

如果对于给定的数据集这些假设不成立,可能仍然可以使用 Kruskal-Wallis H 检验 (scipy.stats.kruskal) 或 Alexander-Govern 测试 (scipy.stats.alexandergovern),尽管可能会有一些功效损失。

每组的长度必须至少为一,且至少有一组的长度大于一。如果这些条件不满足,会生成警告并返回 (np.nan, np.nan)。

如果每组中的所有值都相同,并且至少存在两组具有不同值,则函数会生成警告并返回 (np.inf, 0)。

如果所有组中的所有值都相同,函数会生成警告并返回 (np.nan, np.nan)。

算法来自 Heiman 的 [2],第 394-7 页。

参考文献

[1]

R. Lowry,《推断统计的概念与应用》,第十四章,2014 年,vassarstats.net/textbook/

[2]

G.W. Heiman,“理解心理学研究方法与统计学:整合导论”,霍顿·米夫林和公司,2001 年。

[3]

G.H. McDonald,“生物统计手册”,单因素方差分析。www.biostathandbook.com/onewayanova.html

例子

>>> import numpy as np
>>> from scipy.stats import f_oneway 

下面是关于贻贝 Mytilus trossulus 的壳测量数据[3](通过除以长度标准化的前附加肌瘢痕长度),来自五个地点的数据:俄勒冈州提拉穆克;俄勒冈州纽波特;阿拉斯加州彼得堡;俄罗斯马加丹;芬兰特瓦尔米内,这些数据来自 McDonald 等人(1991 年)使用的大数据集。

>>> tillamook = [0.0571, 0.0813, 0.0831, 0.0976, 0.0817, 0.0859, 0.0735,
...              0.0659, 0.0923, 0.0836]
>>> newport = [0.0873, 0.0662, 0.0672, 0.0819, 0.0749, 0.0649, 0.0835,
...            0.0725]
>>> petersburg = [0.0974, 0.1352, 0.0817, 0.1016, 0.0968, 0.1064, 0.105]
>>> magadan = [0.1033, 0.0915, 0.0781, 0.0685, 0.0677, 0.0697, 0.0764,
...            0.0689]
>>> tvarminne = [0.0703, 0.1026, 0.0956, 0.0973, 0.1039, 0.1045]
>>> f_oneway(tillamook, newport, petersburg, magadan, tvarminne)
F_onewayResult(statistic=7.121019471642447, pvalue=0.0002812242314534544) 

f_oneway 接受多维输入数组。当输入是多维的且未给定axis时,测试沿输入数组的第一个轴执行。对于以下数据,测试将执行三次,每次对应每列数据。

>>> a = np.array([[9.87, 9.03, 6.81],
...               [7.18, 8.35, 7.00],
...               [8.39, 7.58, 7.68],
...               [7.45, 6.33, 9.35],
...               [6.41, 7.10, 9.33],
...               [8.00, 8.24, 8.44]])
>>> b = np.array([[6.35, 7.30, 7.16],
...               [6.65, 6.68, 7.63],
...               [5.72, 7.73, 6.72],
...               [7.01, 9.19, 7.41],
...               [7.75, 7.87, 8.30],
...               [6.90, 7.97, 6.97]])
>>> c = np.array([[3.31, 8.77, 1.01],
...               [8.25, 3.24, 3.62],
...               [6.32, 8.81, 5.19],
...               [7.48, 8.83, 8.91],
...               [8.59, 6.01, 6.07],
...               [3.07, 9.72, 7.48]])
>>> F, p = f_oneway(a, b, c)
>>> F
array([1.75676344, 0.03701228, 3.76439349])
>>> p
array([0.20630784, 0.96375203, 0.04733157]) 

scipy.stats.tukey_hsd

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.tukey_hsd.html#scipy.stats.tukey_hsd

scipy.stats.tukey_hsd(*args)

对多个处理进行 Tukey's HSD 测试以比较均值的等性。

Tukey's HSD(Tukey 的显著差异)测试对一组样本执行均值的两两比较。而方差分析(如f_oneway)评估每个样本底层真实均值是否相同,Tukey's HSD 则是用于比较每个样本均值与其他每个样本均值的事后检验。

零假设是样本底层分布的均值相同。计算每个可能的样本配对的检验统计量,其实就是样本均值之差。对于每对,p 值是在零假设下(及其他假设;见注意事项)观察到统计量的极端值的概率,考虑到正在执行许多两两比较。还提供了每对均值差异的置信区间。

参数:

**sample1, sample2, …**array_like

每组的样本测量值。至少必须有两个参数。

返回:

resultTukeyHSDResult 实例

返回值是具有以下属性的对象:

statisticfloat ndarray

每次比较的测试统计量。索引(i, j)处的元素是组ij之间的统计量。

pvaluefloat ndarray

每次比较的测试 p 值。索引(i, j)处的元素是组ij之间的 p 值。

该对象具有以下方法:

confidence_interval(confidence_level=0.95):

计算指定置信水平的置信区间。

另见

dunnett

对比一组控制组的均值。

注意事项

该测试的使用依赖于几个假设。

  1. 观测值在组内和组间是独立的。

  2. 每组内和组间的观测值均服从正态分布。

  3. 从中抽取样本的分布具有相同的有限方差。

测试的原始制定是针对相等样本大小的 [6]。在样本大小不等的情况下,测试使用 Tukey-Kramer 方法 [4]

参考文献

[1]

NIST/SEMATECH 统计方法电子手册,“7.4.7.1. Tukey 方法。” www.itl.nist.gov/div898/handbook/prc/section4/prc471.htm,2020 年 11 月 28 日。

[2]

Abdi, Herve & Williams, Lynne. (2021). “Tukey's Honestly Significant Difference (HSD) Test.” personal.utdallas.edu/~herve/abdi-HSD2010-pretty.pdf

[3]

“使用 SAS PROC ANOVA 和 PROC GLM 进行单因素方差分析.” SAS 教程, 2007, www.stattutorials.com/SAS/TUTORIA….

[4]

Kramer, Clyde Young. “扩展多重范围检验以处理具有不等复制次数的组均值.” 生物统计学, vol. 12, no. 3, 1956, pp. 307-310. JSTOR, www.jstor.org/stable/3001…. 访问于 2021 年 5 月 25 日.

[5]

NIST/SEMATECH 统计方法电子手册, “7.4.3.3. 方差分析表及均值假设检验” www.itl.nist.gov/div898/handbook/prc/section4/prc433.htm, 2021 年 6 月 2 日.

[6]

Tukey, John W. “Comparing Individual Means in the Analysis of Variance.” 生物统计学, vol. 5, no. 2, 1949, pp. 99-114. JSTOR, www.jstor.org/stable/3001…. 访问于 2021 年 6 月 14 日。

示例

这里是比较三种头痛药物的缓解时间的数据,单位为分钟。数据改编自 [3]

>>> import numpy as np
>>> from scipy.stats import tukey_hsd
>>> group0 = [24.5, 23.5, 26.4, 27.1, 29.9]
>>> group1 = [28.4, 34.2, 29.5, 32.2, 30.1]
>>> group2 = [26.1, 28.3, 24.3, 26.2, 27.8] 

我们希望查看各组均值是否显著不同。首先,通过箱线图进行视觉检查。

>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 1)
>>> ax.boxplot([group0, group1, group2])
>>> ax.set_xticklabels(["group0", "group1", "group2"]) 
>>> ax.set_ylabel("mean") 
>>> plt.show() 

../../_images/scipy-stats-tukey_hsd-1_00_00.png

从箱线图中,我们可以看到第 1 组到第 2 组和第 3 组的四分位数范围有重叠,但我们可以应用 tukey_hsd 测试以确定均值差异是否显著。我们设置显著水平为 .05 以拒绝零假设。

>>> res = tukey_hsd(group0, group1, group2)
>>> print(res)
Tukey's HSD Pairwise Group Comparisons (95.0% Confidence Interval)
Comparison  Statistic  p-value   Lower CI   Upper CI
(0 - 1)     -4.600      0.014     -8.249     -0.951
(0 - 2)     -0.260      0.980     -3.909      3.389
(1 - 0)      4.600      0.014      0.951      8.249
(1 - 2)      4.340      0.020      0.691      7.989
(2 - 0)      0.260      0.980     -3.389      3.909
(2 - 1)     -4.340      0.020     -7.989     -0.691 

零假设是每组具有相同的均值。对比 group0group1,以及 group1group2 的 p 值均不超过 .05,因此我们拒绝它们具有相同均值的零假设。对比 group0group2 的 p 值超过 .05,因此我们接受它们均值无显著差异的零假设。

我们还可以计算与我们选择的置信水平相关的置信区间。

>>> group0 = [24.5, 23.5, 26.4, 27.1, 29.9]
>>> group1 = [28.4, 34.2, 29.5, 32.2, 30.1]
>>> group2 = [26.1, 28.3, 24.3, 26.2, 27.8]
>>> result = tukey_hsd(group0, group1, group2)
>>> conf = res.confidence_interval(confidence_level=.99)
>>> for ((i, j), l) in np.ndenumerate(conf.low):
...     # filter out self comparisons
...     if i != j:
...         h = conf.high[i,j]
...         print(f"({i} - {j}) {l:>6.3f}  {h:>6.3f}")
(0 - 1) -9.480  0.280
(0 - 2) -5.140  4.620
(1 - 0) -0.280  9.480
(1 - 2) -0.540  9.220
(2 - 0) -4.620  5.140
(2 - 1) -9.220  0.540 

scipy.stats.dunnett

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.dunnett.html#scipy.stats.dunnett

scipy.stats.dunnett(*samples, control, alternative='two-sided', random_state=None)

Dunnett’s 测试:多个组的平均值与控制组的比较。

这是 Dunnett 原始的单步测试实现,如[1]所述。

参数:

**sample1, sample2, …**1D 数组样本

每个实验组的样本测量。

control1D 数组样本

控制组的样本测量。

alternative{‘双边’, ‘less’, ‘greater’},可选

定义备择假设。

零假设是样本分布和控制组分布的平均值相等。可用以下备择假设(默认为‘双边’):

  • ‘two-sided’: 样本和控制组的分布平均值不等。

  • ‘less’: 样本分布的平均值小于控制组分布的平均值。

  • ‘greater’: 样本分布的平均值大于控制组分布的平均值。

random_state{None, int, numpy.random.Generator}, 可选

如果random_state是 int 或 None,则使用np.random.default_rng(random_state)创建一个新的numpy.random.Generator。如果random_state已经是Generator实例,则使用提供的实例。

随机数生成器用于控制多元 t 分布的随机化拟蒙特卡罗积分。

返回:

resDunnettResult

包含属性的对象:

统计量的浮点数 ndarray

每次比较的测试计算统计量。索引i处的元素是组i与控制组之间的统计量。

p 值的浮点数 ndarray

每次比较的测试的计算 p 值。索引i处的元素是组i与控制组之间的 p 值。

以及以下方法:

confidence_interval(confidence_level=0.95):

计算组的平均值与控制组加减允许范围的差异。

另见

tukey_hsd

执行平均值的成对比较。

注意事项

像独立样本 t 检验一样,邓特氏检验[1]用于对样本抽样分布的均值进行推断。然而,当以固定显著性水平执行多个 t 检验时,“家族误差率” - 在至少一个测试中错误拒绝零假设的概率 - 将超过显著性水平。邓特氏检验旨在在控制家族误差率的同时进行多重比较。

邓特氏检验比较多个实验组与单一对照组的均值。Tukey 的 Honestly Significant Difference Test 是另一种控制家族误差率的多重比较测试,但tukey_hsd进行所有成对组间比较。当不需要实验组间的成对比较时,邓特氏检验由于具有更高的功效而更可取。

此测试的使用依赖于几个假设。

  1. 观察在组内和组间是独立的。

  2. 每组观察值符合正态分布。

  3. 抽样分布具有相同的有限方差。

参考资料

[1] (1,2,3)

Charles W. Dunnett. “A Multiple Comparison Procedure for Comparing Several Treatments with a Control.” 美国统计协会杂志, 50:272, 1096-1121, DOI:10.1080/01621459.1955.10501294, 1955.

例子

[1]中,研究了药物对三组动物血细胞计数测量的影响。

下表总结了实验结果,其中两组接受不同药物,而一组作为对照。记录了血细胞计数(每立方毫米百万细胞数):

>>> import numpy as np
>>> control = np.array([7.40, 8.50, 7.20, 8.24, 9.84, 8.32])
>>> drug_a = np.array([9.76, 8.80, 7.68, 9.36])
>>> drug_b = np.array([12.80, 9.68, 12.16, 9.20, 10.55]) 

我们想看看各组的平均值是否显著不同。首先,通过箱线图进行视觉检查。

>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots(1, 1)
>>> ax.boxplot([control, drug_a, drug_b])
>>> ax.set_xticklabels(["Control", "Drug A", "Drug B"])  
>>> ax.set_ylabel("mean")  
>>> plt.show() 

../../_images/scipy-stats-dunnett-1_00_00.png

注意药物 A 组和对照组的重叠四分位范围以及药物 B 组和对照组之间的明显分离。

接下来,我们将使用邓特氏检验来评估组间均值差异是否显著,同时控制家族误差率:即可能发生任何虚假发现的概率。设定零假设为实验组与对照组均值相同,备择假设为实验组与对照组均值不同。我们将考虑 5%的家族误差率是可接受的,因此我们选择 0.05 作为显著性阈值。

>>> from scipy.stats import dunnett
>>> res = dunnett(drug_a, drug_b, control=control)
>>> res.pvalue
array([0.62004941, 0.0059035 ])  # may vary 

在组 A 和对照组之间进行比较的 p 值超过了 0.05,因此我们在这个比较中不拒绝原假设。然而,在组 B 和对照组之间进行比较的 p 值小于 0.05,因此我们认为实验结果支持备择假设:组 B 的均值与对照组不同。

scipy.stats.kruskal

原文:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.kruskal.html#scipy.stats.kruskal

scipy.stats.kruskal(*samples, nan_policy='propagate', axis=0, keepdims=False)

计算独立样本的 Kruskal-Wallis H 检验。

Kruskal-Wallis H 检验检验假设,即所有组的总体中位数相等。这是方差分析的非参数版本。该检验适用于两个或更多个独立样本,这些样本可能具有不同的大小。请注意,拒绝原假设并不表示哪些组之间不同。需要进行事后比较以确定哪些组不同。

参数:

**sample1, sample2, …**array_like

可以将两个或更多个数组与样本测量值作为参数给出。样本必须是一维的。

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

定义如何处理输入的 NaN。

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

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

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

axisint 或 None,默认值:0

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

keepdimsbool,默认值:False

如果设置为 True,则减少的轴将作为尺寸为一的维度留在结果中。使用此选项,结果将正确传播到输入数组。

返回:

statisticfloat

经校正的 Kruskal-Wallis H 统计量,考虑到并列。

pvaluefloat

使用假设 H 服从卡方分布的测试的 p 值。返回的 p 值是在 H 处评估的卡方分布的生存函数。

另请参见

f_oneway

1-way ANOVA.

mannwhitneyu

两个样本的曼-惠特尼秩和检验。

friedmanchisquare

重复测量的弗里德曼检验。

注意事项

由于假设 H 服从卡方分布,每个组中的样本数量不能太少。典型规则是每个样本必须至少有 5 次测量。

从 SciPy 1.9 开始,np.matrix 输入(不建议在新代码中使用)在执行计算之前会转换为 np.ndarray。在这种情况下,输出将是适当形状的标量或 np.ndarray,而不是 2D 的 np.matrix。类似地,尽管掩码数组的掩码元素被忽略,输出将是标量或 np.ndarray,而不是具有 mask=False 的掩码数组。

参考

[1]

W. H. Kruskal & W. W. Wallis,《使用排名进行单因素方差分析》,《美国统计协会杂志》,第 47 卷,260 期,第 583-621 页,1952 年。

[2]

en.wikipedia.org/wiki/Kruskal-Wallis_one-way_analysis_of_variance

示例

>>> from scipy import stats
>>> x = [1, 3, 5, 7, 9]
>>> y = [2, 4, 6, 8, 10]
>>> stats.kruskal(x, y)
KruskalResult(statistic=0.2727272727272734, pvalue=0.6015081344405895) 
>>> x = [1, 1, 1]
>>> y = [2, 2, 2]
>>> z = [2, 2]
>>> stats.kruskal(x, y, z)
KruskalResult(statistic=7.0, pvalue=0.0301973834223185) 

scipy.stats.alexandergovern

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.alexandergovern.html#scipy.stats.alexandergovern

scipy.stats.alexandergovern(*samples, nan_policy='propagate')

执行 Alexander Govern 检验。

Alexander-Govern 近似检验在方差异质性情况下测试 k 个独立均值的相等性。该检验适用于来自两个或多个组的样本,可能具有不同的大小。

参数:

**sample1, sample2, …**array_like

每组的样本测量。至少需要两个样本。

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

定义如何处理包含 NaN 的输入。提供以下选项(默认为‘propagate’):

  • ‘propagate’: 返回 NaN

  • ‘raise’: 抛出错误

  • ‘omit’: 在计算时忽略 NaN 值

返回:

resAlexanderGovernResult

具有属性的对象:

statisticfloat

测试的计算 A 统计量。

pvaluefloat

从卡方分布中得到的关联 p 值。

警告:

ConstantInputWarning

如果输入是常数数组,则引发错误。在这种情况下,统计量未定义,因此返回np.nan

另请参阅

f_oneway

单因素方差分析

注意事项

此检验的使用依赖于几个假设。

  1. 样本是独立的。

  2. 每个样本来自正态分布的总体。

  3. f_oneway不同,此检验不假设同方差性,而是放宽了等方差性的假设。

输入样本必须是有限的、一维的,并且大小大于一。

参考文献

[1]

Alexander, Ralph A., 和 Diane M. Govern. “A New and Simpler Approximation for ANOVA under Variance Heterogeneity.” Journal of Educational Statistics, vol. 19, no. 2, 1994, pp. 91-101. JSTOR, www.jstor.org/stable/1165…. 访问日期:2020 年 9 月 12 日。

示例

>>> from scipy.stats import alexandergovern 

这里提供了来自美国四个城市九家最大银行新车贷款年利率的一些数据,取自国家标准技术研究所的 ANOVA 数据集。

我们使用alexandergovern来检验所有城市的平均年利率百分比是否相同的零假设,对立假设是不是所有城市的平均年利率百分比都不相同。我们决定在显著性水平为 5%时拒绝零假设,支持备择假设。

>>> atlanta = [13.75, 13.75, 13.5, 13.5, 13.0, 13.0, 13.0, 12.75, 12.5]
>>> chicago = [14.25, 13.0, 12.75, 12.5, 12.5, 12.4, 12.3, 11.9, 11.9]
>>> houston = [14.0, 14.0, 13.51, 13.5, 13.5, 13.25, 13.0, 12.5, 12.5]
>>> memphis = [15.0, 14.0, 13.75, 13.59, 13.25, 12.97, 12.5, 12.25,
...           11.89]
>>> alexandergovern(atlanta, chicago, houston, memphis)
AlexanderGovernResult(statistic=4.65087071883494,
 pvalue=0.19922132490385214) 

p 值为 0.1992,表示在零假设下观察到这样一个极端值的几率接近 20%。这超过了 5%,因此我们不拒绝零假设,支持备择假设。

scipy.stats.fligner

原文链接:docs.scipy.org/doc/scipy-1.12.0/reference/generated/scipy.stats.fligner.html#scipy.stats.fligner

scipy.stats.fligner(*samples, center='median', proportiontocut=0.05, axis=0, nan_policy='propagate', keepdims=False)

执行 Fligner-Killeen 检验以检验方差的相等性。

Fligner 的检验检验的是所有输入样本来自方差相等的总体的零假设。当总体相同时,Fligner-Killeen 的检验是分布自由的 [2]

参数:

**sample1, sample2, …**array_like

样本数据数组。不需要具有相同的长度。

center{‘mean’, ‘median’, ‘trimmed’},可选

控制在计算检验统计量时使用数据的函数的关键字参数。默认为 ‘median’。

proportiontocutfloat,可选

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

axisint 或 None,默认值:0

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

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

定义如何处理输入的 NaN 值。

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

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

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

keepdimsbool,默认值:False

如果设置为 True,则减少的轴将作为大小为一的维度保留在结果中。使用此选项,结果将正确地与输入数组广播。

返回:

statisticfloat

检验统计量。

pvaluefloat

假设检验的 p 值。

参见

bartlett

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

levene

一个关于 k 方差相等性的鲁棒参数检验

注意

与 Levene 的检验类似,Fligner 的检验有三个变体,它们在测试中使用的集中趋势测量方法不同。详见 levene 获取更多信息。

康诺弗等人(1981)通过广泛的模拟研究了许多现有的参数和非参数检验方法,他们得出结论,Fligner 和 Killeen(1976)以及 Levene(1960)提出的检验方法在对正态性偏差和功效的鲁棒性方面似乎更为优越 [3]

从 SciPy 1.9 开始,不推荐使用的 np.matrix 输入在进行计算之前将被转换为 np.ndarray。在这种情况下,输出将是适当形状的标量或 np.ndarray,而不是二维 np.matrix。同样,忽略掩码数组的掩码元素后,输出将是一个标量或 np.ndarray,而不是具有 mask=False 的掩码数组。

参考文献

[1]

Park, C. 和 Lindsay, B. G. (1999). 鲁棒的尺度估计和基于二次推理函数的假设检验。宾夕法尼亚州立大学可能性研究中心技术报告 #99-03。cecas.clemson.edu/~cspark/cv/paper/qif/draftqif2.pdf

[2]

Fligner, M.A. 和 Killeen, T.J. (1976). Distribution-free two-sample tests for scale. ‘Journal of the American Statistical Association.’ 71(353), 210-213.

[3]

Park, C. 和 Lindsay, B. G. (1999). 鲁棒的尺度估计和基于二次推理函数的假设检验。宾夕法尼亚州立大学可能性研究中心技术报告 #99-03。

[4]

Conover, W. J., Johnson, M. E. 和 Johnson M. M. (1981). 各种方差同质性检验的比较研究,适用于外大陆架招标数据。技术统计学,23(4),351-361。

[5]

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

[6]

B. Phipson 和 G. K. Smyth. “当置换是随机抽取时,永远不应为零:计算精确的 P 值。” 遗传学和分子生物学统计应用 9.1 (2010).

[7]

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

示例

[5] 中,研究了维生素 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
... ]) 

fligner 统计量对样本之间方差的差异很敏感。

>>> from scipy import stats
>>> res = stats.fligner(small_dose, medium_dose, large_dose)
>>> res.statistic
1.3878943408857916 

当方差存在显著差异时,统计量的值往往较高。

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

对于这个检验,零假设分布如下,遵循卡方分布。

>>> import matplotlib.pyplot as plt
>>> k = 3  # number of samples
>>> dist = stats.chi2(df=k-1)
>>> val = np.linspace(0, 8, 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("Fligner Test Null Distribution")
...     ax.set_xlabel("statistic")
...     ax.set_ylabel("probability density")
...     ax.set_xlim(0, 8)
...     ax.set_ylim(0, 0.5)
>>> plot(ax)
>>> plt.show() 

../../_images/scipy-stats-fligner-1_00_00.png

比较由 p 值量化:在零分布中大于或等于统计量的观察值的比例。

>>> fig, ax = plt.subplots(figsize=(8, 5))
>>> plot(ax)
>>> pvalue = dist.sf(res.statistic)
>>> annotation = (f'p-value={pvalue:.4f}\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-fligner-1_01_00.png

>>> res.pvalue
0.49960016501182125 

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

  • 反之不成立;也就是说,该检验不能用来支持零假设。

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

  • 小的 p 值并不是支持 效应的证据;相反,它们只能提供“显著”效应的证据,意味着在零假设下发生这些情况的可能性很小。

注意,卡方分布提供了零分布的渐近近似。对于小样本,执行置换检验可能更合适:在零假设下,三个样本都是从同一总体抽取的,每个测量在三个样本中的观察概率相同。因此,我们可以通过在观察数据的许多随机分区下计算统计量来形成随机化的零分布。

>>> def statistic(*samples):
...     return stats.fligner(*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, 8, 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-fligner-1_02_00.png

>>> ref.pvalue  # randomized test p-value
0.4332  # may vary 

请注意,这里计算的 p 值与上述 fligner 返回的渐近近似存在显著分歧。从置换检验中可以严谨地推断的统计推断是有限的;尽管如此,在许多情况下,它们可能是首选的方法[7]

接下来是另一个通用示例,拒绝零假设的情况。

测试列表 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.fligner(a, b, c)
>>> p
0.00450826080004775 

小的 p 值表明这些群体的方差不相等。

鉴于 b 的样本方差远大于 ac 的样本方差,这并不令人意外:

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