Fisher精确检验(Fisher’s Exact Test)
适用于分析2×2列联表(如治疗 vs. 不治疗,生存 vs. 死亡),特别适用于小样本数据(如某些单元格期望计数 <5)。
| 生存 | 死亡 | 总计 | |
|---|---|---|---|
| 治疗组 | 8 | 2 | 10 |
| 对照组 | 3 | 7 | 10 |
| 总计 | 11 | 9 | 20 |
2. Fisher检验的原假设(H₀)
H₀:治疗与生存率无关(即治疗对生存率无影响)。
换句话说,治疗组和对照组的生存/死亡比例来自同一个总体分布。
3. 抽球原理类比
- 想象一个袋子中有 20个球(代表所有受试者):
- 11个白球(生存)
- 9个黑球(死亡)
- 随机抽取10个球(治疗组),剩下的10个是对照组。
- 问题:如果治疗无效,治疗组中抽到8个白球(生存)的概率是多少?
Fisher检验的核心
计算在H₀成立时,观察到当前表格(或更极端情况)的超几何概率:
(即治疗组生存数≥8的概率)
4. R语言实现
# 构造列联表
data <- matrix(c(8, 2, 3, 7), nrow = 2, byrow = TRUE)
rownames(data) <- c("治疗组", "对照组")
colnames(data) <- c("生存", "死亡")
# Fisher精确检验
fisher.test(data)输出结果
p-value = 0.0345
alternative hypothesis: true odds ratio is not equal to 1
- p值=0.0345(<0.05),拒绝H₀,说明治疗与生存率显著相关。
- 显著性:p值<0.05,表明治疗组和对照组的生存率差异非随机产生。
- 方向性:治疗组生存率(8/10=80%)高于对照组(3/10=30%)。
- 优势比(Odds Ratio):
治疗组的死亡风险是对照组的1/9.33≈0.11倍(保护效应)。
- H₀:治疗与生存无关(两组生存率相同)。
- 检验原理:通过超几何分布计算极端情况的概率。
- 适用场景:小样本、2×2列联表,尤其当卡方检验不满足条件时。
- 结论:本例中治疗显著提高生存率(p=0.0345)。
列联表行/列转置是否影响Fisher检验结果?
1. 转置后的列联表
原始表(生存/死亡在列):
| 生存 | 死亡 | 总计 | |
|---|---|---|---|
| 治疗组 | 8 | 2 | 10 |
| 对照组 | 3 | 7 | 10 |
| 总计 | 11 | 9 | 20 |
转置后(生存/死亡在行):
| 治疗组 | 对照组 | 总计 | |
|---|---|---|---|
| 生存 | 8 | 3 | 11 |
| 死亡 | 2 | 7 | 9 |
| 总计 | 10 | 10 | 20 |
2. Fisher检验的数学本质
-
检验的假设(H₀)不变:
- 原假设始终是行变量与列变量独立(如治疗与生存无关)。
- 转置仅改变表格的展示方式,不改变变量间的关系。
-
统计量计算不受影响:
Fisher检验基于超几何分布,其概率公式为:
其中 是四格表的单元格值, 是总样本量。
转置后,单元格的数学关系保持不变(如原始表的 仍是转置后的 )。
3. R语言验证
# 原始表(生存/死亡在列)
data_original <- matrix(c(8, 2, 3, 7), nrow = 2, byrow = TRUE)
fisher.test(data_original)$p.value # 输出: 0.0345
# 转置后(生存/死亡在行)
data_transposed <- t(data_original)
fisher.test(data_transposed)$p.value # 输出: 0.0345结果一致,p值均为0.0345。
4. 解释的侧重点差异
虽然统计结论相同,但转置可能影响结果表述的侧重点:
- 原始表:
- 解释为“治疗组的生存率是否显著高于对照组”。
- 转置表:
- 解释为“生存组的治疗比例是否显著高于死亡组”。
Q1: alternative = "less" 是否计算 4/3/2…个球的概率?
- 是。
- 如果当前抽到 5 个白球,
less计算的是抽到 ≤5 个白球的概率(即 0,1,2,3,4,5)。 - 但若当前观察值已在左侧(如 2 个白球),
less会计算更小值(0,1,2)。
- 如果当前抽到 5 个白球,
Q2: alternative = "greater" 是否计算 5/6/7…个球的概率?
- 是。
- 如果当前抽到 5 个白球,
greater计算的是抽到 ≥5 个白球的概率(即 5,6,7,…)。
- 如果当前抽到 5 个白球,
Q3: two.sided(双尾)的计算逻辑?
- 不是简单的左尾+右尾,而是:
- 计算所有与当前表格或更极端情况的概率(按优势比定义极端性)。
- 例如:若当前表格的 OR=4,则双尾 p值包括所有 OR≥4 或 OR≤1/4 的表格概率之和。
4. R代码验证
data <- matrix(c(8, 2, 3, 7), nrow = 2)
# 右尾检验(治疗组生存率 > 对照组)
fisher.test(data, alternative = "greater")$p.value # 输出: 0.017
# 左尾检验(治疗组生存率 < 对照组)
fisher.test(data, alternative = "less")$p.value # 输出: 0.99
# 双尾检验(默认)
fisher.test(data, alternative = "two.sided")$p.value # 输出: 0.0345核心要点
- 单尾检验需预先指定方向,不可根据数据结果事后选择。
- 双尾检验是默认选择,除非有强理论支持单侧假设。
- Fisher检验的 p值基于超几何分布的极端概率累加。
- 总球数
- 成功球(标记为“白球”)数
- 失败球(“黑球”)数
- 抽取数
假设你观察到抽到 个成功球。
2. 超几何概率分布(抽出成功球数的概率)
公式:
我们先计算所有可能的 的概率:
| x(成功数) | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| P(X=x) | 0.0002 | 0.0021 | 0.0113 | 0.0391 | 0.0916 | 0.1501 | 0.1881 | 0.1686 | 0.1048 | 0.0363 | 0.0080 |
3. 各种 alternative 计算的 p 值区域
假设观察到 :
- “less”:计算
- “greater”:计算
- “two.sided”:计算所有概率 ≤ 的概率和
4. 哪些值“更极端”?
- 找所有 使得 ,包括 (因为 , 都大于 0.1501)
所以,
# 原始列联表(治疗为行,生存和死亡为列)
# 生存 死亡
# 治疗 8 2
# 未治疗 4 6
table_orig <- matrix(c(8, 2, 4, 6), nrow=2, byrow=F)
rownames(table_orig) <- c("治疗", "未治疗")
colnames(table_orig) <- c("生存", "死亡")
print("原始列联表:")
print(table_orig)
# Fisher检验 alternative = "greater" # 检验治疗组“生存”数量更多
res_orig_greater <- fisher.test(table_orig, alternative = "greater")
print("原始表 alternative = 'greater' (治疗组生存数更多):")
print(res_orig_greater$p.value)
# Fisher检验 alternative = "less" # 检验治疗组“生存”数量更少
res_orig_less <- fisher.test(table_orig, alternative = "less")
print("原始表 alternative = 'less' (治疗组生存数更少):")
print(res_orig_less$p.value)
# 交换“生存”和“死亡”两列,列顺序变为死亡-生存
table_swap <- table_orig[, c("死亡", "生存")]
print("交换列后列联表(死亡和生存列顺序交换):")
print(table_swap)
# 这时如果仍用 alternative = "greater",其实检验的是治疗组“死亡”数量是否更多
res_swap_greater <- fisher.test(table_swap, alternative = "greater")
print("交换列后 alternative = 'greater' (治疗组死亡数更多):")
print(res_swap_greater$p.value)
# alternative = "less" 检验治疗组“死亡”数量是否更少
res_swap_less <- fisher.test(table_swap, alternative = "less")
print("交换列后 alternative = 'less' (治疗组死亡数更少):")
print(res_swap_less$p.value)