scipy.stats.

fisher_exact#

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

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

原假设是基础群体中的真实比值等于 1,并且在以下条件下对这些群体进行采样获得这些观察值:结果表的边际值必须等于观察到表的边际值。返回的统计数据为比值的无条件最大似然估计值,p 值在原假设下获得一个比实际观察到的表更极端的值的概率。对于 Fisher 精确检验,有其他可能的统计量和两面 p 值定义;有关更多信息,请参阅附注。

参数:
tableint 类型数组_like

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

alternative{‘two-sided’, ‘less’, ‘greater’}, 非必需

定义备选假设。提供以下选项(默认值为 ‘two-sided’)

  • ‘two-sided’:基础群体的比值不等于 1

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

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

有关更多详细信息,请参阅附注。

返回:
res显着性结果

包含属性的对象

statisticfloat

这是先验比值,不是后验估计。

pvaluefloat

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

另请参阅

chi2_contingency

列联表中变量独立性的卡方检验。当表中的数字很大时,这可以作为 fisher_exact 的替代方案。

contingency.odds_ratio

计算 2x2 列联表的比值(样本或条件 MLE)。

barnard_exact

巴纳德精确检验,这是一种比 Fisher 精确检验针对 2x2 列联表功能强大的替代方法。

boschloo_exact

博施洛精确检验,这是一种比 Fisher 精确检验针对 2x2 列联表功能强大的替代方法。

注释

零假设和 p 值

零假设是观察基础人群的真实比值为一,并且在一种条件下从这些群中随机抽取观察:所得表的边际必须等于观察到的表的边际。同样,零假设是输入表来自超几何分布并且具有参数(正如在 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 小 1,因为我们希望在求和中包括 x = 6 的概率)处计算分布的生存函数

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

对于 alternative='less',单边 p 值是随机表具有 x <= a 的概率(即我们示例中的 x <= 60.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]

Fisher,Sir Ronald A,"实验设计:一位品茶女士的数学"。ISBN 978-0-486-41151-4,1935 年。

[2]

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

[3]

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

示例

[3] 中,研究了用于预防急性高山病的乙酰唑胺有效剂量。该研究值得注意的结论是

250 毫克、500 毫克和 750 毫克的每日乙酰唑胺对于预防急性高山病都非常有效。对于此适应症,250 毫克的乙酰唑胺是最低有效剂量,具有足够证据支持。

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

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

是否有证据表明 250 毫克乙酰唑胺可以降低急性高山病的风险?我们从制定原假设 \(H_0\) 开始

服用乙酰唑胺治疗时出现急性高山病的可能性与服用安慰剂时出现急性高山病的可能性相同。

让我们用 Fisher 检验评估这一假设的合理性。

>>> 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 值小于。