第四章 Bonferroni 校正:原理、适用场景、优缺点
多重假设检验的麻烦,我估计做 RNA-seq 的人都深有体会。几千个基因同时做差异表达检验,随便一筛就能冒出几百个“显著”基因,可到底有多少是真的?
Bonferroni 校正,就是最早、最经典、也最让人又爱又恨的一刀切办法。它的逻辑很简单:你想把整体假阳性率(FWER)控制在 0.05,那就把每个检验的阈值除以检验次数。
4.1 原理:到底在调整什么?
咱们不绕弯子,直接说公式:
p_corrected = p_raw × N
如果 p_corrected < 0.05,则拒绝 H₀
其中 N 是总检验数,或者说比较次数。更严格的说法是 Bonferroni 不等式:
P(至少一个假阳性) ≤ N × α
所以设定每个检验的显著性水平为 α / N
举个例子:你做了 10000 个基因的差异检验,原始 p 值 0.000005,那校正后就是 0.05。恰好卡在 0.05 线上,正好显著。如果原始 p 是 0.001,校正后变成 10 —— 远远超过 1,根本不可能显著。
说白了,就是把门槛提到极高,宁可错杀一千,也不放过一个假阳性。
4.2 适用场景:什么时候该用它?
我自己的经验是,Bonferroni 只适合两种情况:
- 目标检验数极少,且要求零容忍假阳性。比如只验证 3~5 个候选基因的 qPCR 数据,或者做染色体层面的 CNV 断点验证。
- 作为保守的下界参考。有时候我会在报告里同时列出 Bonferroni 和 FDR 校正的结果,用来展示“最严格情况是什么样”。
但它在 RNA-seq 全转录组分析里基本是灾难。为什么?
4.3 优缺点:这把刀的双刃
| 优点 | 缺点 |
|---|---|
| 控制 FWER 非常严格,没有任何松动 | 极度保守,容易漏掉真实差异 |
| 计算方法简单,手工也能算 | 假定所有检验相互独立——实际基因表达高度相关 |
| 对任何分布都成立,无需统计假设 | 当 N 很大时,几乎没有基因能通过 |
| 适合少量先验假设的验证 | 无法给出排名,只有 0/1 判断 |
我曾经接手一个项目,合作方坚持用 Bonferroni 校正筛选差异基因,结果 20000 个基因只出来 2 个。后来我换用 BH 方法,发现了 87 个,再通过 RT-qPCR 验证了其中 11 个,全部得到确认。所以 Bonferroni 的“保守”有时候是虚假的严谨——它只是把假阴性堆得很高。
4.4 在 R 中实现与误区
R 里实现很简单:
# 原始 p 值向量,假设有 20000 个
p_raw <- runif(20000, min=0, max=1)
# Bonferroni 校正
p_bonf <- p.adjust(p_raw, method = "bonferroni")
# 看看显著基因数量
sum(p_bonf < 0.05)
# 等价手动计算
p_bonf_manual <- pmin(p_raw * length(p_raw), 1)
注意 pmin 的使用:校正后的 p 值不能超过 1,因为概率不可能大于 1。有些老代码忘了加这一步,结果出现大于 1 的“p 值”,那就不对了。
4.5 知识结构总览
4.6 什么时候该果断说“不”
我个人的原则很简单:
- 如果你的分析涉及上千次检验,别用 Bonferroni。
- 如果你的目标是从无假设中找到新基因,别用 Bonferroni。
- 如果你的样本量小、组间差异弱,更别碰它——结果会让你怀疑人生。
但反过来,当你被审稿人要求“请严格控制多重比较的假阳性率”时,拿出 Bonferroni 校正的结果作为最坏情况的参照,倒是一个很有效的答辩策略。有点像是:告诉对方“看,即使我用最极端的方法,这些基因还是显著的”。