scipy.stats.

fisher_exact#

scipy.stats.fisher_exact(table, alternative=None, *, method=None)[source]#

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

对于 2x2 表,零假设是观测值的基础总体的真实优势比为 1,并且观测值是在某种条件下从这些总体中抽样的:所得表的边际必须等于观测表的边际。统计量是优势比的无条件最大似然估计,p 值是在零假设下获得至少与实际观测到的表一样极端的表的概率。

对于其他表大小,或者如果提供了 method,则零假设是表的行和列具有固定的总和并且是独立的;即,该表是从具有观察到的边际的 scipy.stats.random_table 分布中抽样的。统计量是此分布在 table 处评估的概率质量,p 值是表的总体中统计量至少与 table 的统计量一样极端(小)的百分比。只有一个备择假设可用:行和列不独立。

Fisher 精确检验还有其他可能的统计量选择和双边 p 值定义;请参阅 Notes 了解更多信息。

参数:
table整数的类数组 (array_like of ints)

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

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

定义 2x2 表的备择假设;对于其他表大小未使用。以下选项可用(默认为“two-sided”)

  • “two-sided”:基础总体的优势比不为 1

  • “less”:基础总体的优势比小于 1

  • “greater”:基础总体的优势比大于 1

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

methodResamplingMethod, 可选

定义用于计算 p 值的方法。如果 methodPermutationMethod/MonteCarloMethod 的实例,则使用 scipy.stats.permutation_test/scipy.stats.monte_carlo_test 以及提供的配置选项和其他适当的设置来计算 p 值。请注意,如果 methodMonteCarloMethod 的实例,则 rvs 属性必须保持未指定;始终使用 scipy.stats.random_tablervs 方法抽取蒙特卡洛样本。否则,p 值的计算方式如 Notes 中所述。

在版本 1.15.0 中添加。

返回:
resSignificanceResult

一个包含属性的对象

statisticfloat

对于具有默认 method 的 2x2 表,这是优势比 - 先验优势比,而不是后验估计。在所有其他情况下,这是在边际固定的情况下,在独立零假设下获得观察到的表的概率密度。

pvaluefloat

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

引发:
ValueError

如果 table 不是二维的或具有负条目。

另请参阅

chi2_contingency

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

contingency.odds_ratio

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

barnard_exact

Barnard 的精确检验,它比 Fisher 的精确检验更强大,适用于 2x2 列联表。

boschloo_exact

Boschloo 的精确检验,它比 Fisher 的精确检验更强大,适用于 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 >= 60.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 <= 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]

Fisher, Sir Ronald A, “The Design of Experiments: Mathematics of a Lady Tasting Tea.” ISBN 978-0-486-41151-4, 1935.

[2]

“Fisher’s exact test”, https://en.wikipedia.org/wiki/Fisher’s_exact_test

示例

>>> from scipy.stats import fisher_exact
>>> res = fisher_exact([[8, 2], [1, 5]])
>>> res.statistic
20.0
>>> res.pvalue
0.034965034965034975

对于形状不是 (2, 2) 的表,为 method 参数提供 scipy.stats.MonteCarloMethodscipy.stats.PermutationMethod 的实例

>>> import numpy as np
>>> from scipy.stats import MonteCarloMethod
>>> rng = np.random.default_rng()
>>> method = MonteCarloMethod(rng=rng)
>>> fisher_exact([[8, 2, 3], [1, 5, 4]], method=method)
SignificanceResult(statistic=np.float64(0.005782), pvalue=np.float64(0.0603))

有关更详细的示例,请参阅 Fisher 的精确检验