scipy.stats.

fisher_exact#

scipy.stats.fisher_exact(table, alternative='two-sided')[源代码][源代码]#

对一个2x2的列联表执行Fisher精确检验。

零假设是,观察值背后的总体的真实优势比为一,并且这些观察值是在以下条件下从这些总体中抽取的:所得表格的边际必须等于观察到的表格的边际。返回的统计量是无条件最大似然估计的优势比,p值是在零假设下获得至少与实际观察到的表格一样极端的表格的概率。费舍尔精确检验还有其他可能的统计量选择和双侧p值定义;请参阅注释以获取更多信息。

参数:
类数组的整数

一个2x2的列联表。元素必须是非负整数。

替代方案{‘双侧’, ‘小于’, ‘大于’}, 可选

定义备择假设。以下选项可用(默认是’双侧’):

  • ‘双侧’: 基础人群的比值比不是一

  • ‘less’: 基础人群的比值比小于1

  • ‘greater’: 基础人群的比值比大于1

更多详情请参见注释。

返回:
res重要性结果

一个包含属性的对象:

统计浮动

这是先验优势比,不是后验估计。

p值浮动

在零假设下,获得一个至少与实际观察到的表格一样极端的表格的概率。

参见

chi2_contingency

卡方检验用于检验列联表中变量的独立性。当表中的数字较大时,可以作为 fisher_exact 的替代方法使用。

contingency.odds_ratio

计算2x2列联表的比值比(样本或条件最大似然估计)。

barnard_exact

Barnard 精确检验,对于 2x2 列联表来说,它比 Fisher 精确检验具有更强的替代性。

boschloo_exact

Boschloo 的精确检验,对于 2x2 列联表来说,是比 Fisher 精确检验更强大的替代方法。

注释

零假设和p值

零假设是观察结果所基于的总体的真实优势比为1,并且这些观察结果是在以下条件下从这些总体中随机抽样的:所得表格的边缘必须等于观察到的表格的边缘。等价地,零假设是输入表格来自具有参数(如在 hypergeom 中使用的)的超几何分布,参数为 M = a + b + c + dn = a + bN = a + c,其中输入表格为 [[a, b], [c, d]]。此分布的支持范围为 max(0, N + n - M) <= x <= min(N, n),或者,就输入表格中的值而言,min(0, a - d) <= x <= a + min(b, c)x 可以解释为2x2表格的左上角元素,因此分布中的表格具有以下形式:

[  x           n - x     ]
[N - x    M - (n + N) + x]

例如,如果:

table = [6  2]
        [1  4]

那么支持范围是 2 <= x <= 7,分布中的表格如下:

[2 6]   [3 5]   [4 4]   [5 3]   [6 2]  [7 1]
[5 0]   [4 1]   [3 2]   [2 3]   [1 4]  [0 5]

每个表的概率由超几何分布 hypergeom.pmf(x, M, n, N) 给出。对于这个例子,这些是(四舍五入到三位有效数字):

x       2      3      4      5       6        7
p  0.0163  0.163  0.408  0.326  0.0816  0.00466

这些可以通过以下方式计算:

>>> import numpy as np
>>> from scipy.stats import hypergeom
>>> table = np.array([[6, 2], [1, 4]])
>>> M = table.sum()
>>> n = table[0].sum()
>>> N = table[:, 0].sum()
>>> start, end = hypergeom.support(M, n, N)
>>> hypergeom.pmf(np.arange(start, end+1), M, n, N)
array([0.01631702, 0.16317016, 0.40792541, 0.32634033, 0.08158508,
       0.004662  ])

双侧p值是在零假设下,随机表的概率等于或小于输入表的概率的概率。在我们的例子中,输入表的概率(其中 x = 6)是 0.0816。概率不超过此值的 x 值是 2、6 和 7,因此双侧p值是 0.0163 + 0.0816 + 0.00466 ~= 0.10256:

>>> from scipy.stats import fisher_exact
>>> res = fisher_exact(table, alternative='two-sided')
>>> res.pvalue
0.10256410256410257

对于 alternative='greater' 的单侧 p 值是随机表中 x >= a 的概率,在我们的例子中是 x >= 6,即 0.0816 + 0.00466 ~= 0.08626:

>>> res = fisher_exact(table, alternative='greater')
>>> res.pvalue
0.08624708624708627

这相当于在 x = 5 处计算分布的生存函数(比输入表中的 x 少一个,因为我们希望在和中包含 x = 6 的概率):

>>> hypergeom.sf(5, M, n, N)
0.08624708624708627

对于 alternative='less',单边 p 值是随机表中 x <= a 的概率(即在我们的例子中 x <= 6),或者 0.0163 + 0.163 + 0.408 + 0.326 + 0.0816 ~= 0.9949:

>>> res = fisher_exact(table, alternative='less')
>>> res.pvalue
0.9953379953379957

这相当于计算分布在 x = 6 处的累积分布函数:

>>> hypergeom.cdf(6, M, n, N)
0.9953379953379957

优势比

计算的比值比与 R 函数 fisher.test 计算的值不同。此实现返回“样本”或“无条件”最大似然估计,而 R 中的 fisher.test 使用条件最大似然估计。要计算比值比的条件最大似然估计,请使用 scipy.stats.contingency.odds_ratio

参考文献

[1]

费舍尔,罗纳德·A 爵士,《实验设计:一位女士品茶的数学》。ISBN 978-0-486-41151-4,1935年。

[2]

“费舍尔精确检验”, https://en.wikipedia.org/wiki/Fisher’s_exact_test

[3]

Emma V. Low 等人。“确定预防急性高山病的乙酰唑胺最低有效剂量:系统评价和荟萃分析。” BMJ, 345, DOI:10.1136/bmj.e6779, 2012.

示例

[3] 中,研究了乙酰唑胺用于预防急性高山病的有效剂量。该研究特别得出结论:

Acetazolamide 250 mg、500 mg 和 750 mg 每日剂量均有效预防急性高山病。Acetazolamide 250 mg 是现有证据中最低的有效剂量,适用于此适应症。

下表总结了实验结果,其中一些参与者每天服用250毫克乙酰唑胺,而其他人服用安慰剂。记录了急性高山病的病例:

                            Acetazolamide   Control/Placebo
Acute mountain sickness            7           17
No                                15            5

是否有证据表明乙酰唑胺250毫克能降低急性高山病的风险?我们首先制定一个零假设 \(H_0\)

急性高山病的发生几率在接受乙酰唑胺治疗和安慰剂治疗时是相同的。

让我们用费舍尔检验来评估这个假设的合理性。

>>> from scipy.stats import fisher_exact
>>> res = fisher_exact([[7, 17], [15, 5]], alternative='less')
>>> res.statistic
0.13725490196078433
>>> res.pvalue
0.0028841933752349743

使用5%的显著性水平,我们将拒绝原假设,支持备择假设:“使用乙酰唑胺治疗急性高山病的几率小于使用安慰剂的几率。”

备注

由于Fisher精确检验的零分布是在假设行和列总和都固定的情况下形成的,因此当应用于行总和未固定的实验时,检验结果是保守的。

在这种情况下,各组的列总和是固定的;每组有22个受试者。但是急性高山病的病例数在实验进行前是不固定的(也不可能固定)。这是一个结果。

Boschloo 的检验不依赖于行和固定的假设,因此在这种情况下,它提供了更强大的检验。

>>> from scipy.stats import boschloo_exact
>>> res = boschloo_exact([[7, 17], [15, 5]], alternative='less')
>>> res.statistic
0.0028841933752349743
>>> res.pvalue
0.0015141406667567101

我们通过 fisher_exact 验证 p 值是否小于。