批次效应校正的基本原则:何时需要校正,何时不应该校正

批次效应校正,听起来像是数据处理的标准步骤对吧?
但说实话,我见过太多人一上来就跑 ComBat,根本不问自己一句:这一步真的该做吗?

我个人习惯把校正比作"动手术"——手术能治病,但也能把好组织切掉。
什么时候该切,什么时候绝不能动刀,这就是本章要聊的核心。

核心原则:校正之前先诊断

判断要不要校正,底层逻辑只有一条:
技术差异是否在掩盖或扭曲生物学信号?

如果技术噪音主导了数据变异,校正就是雪中送炭。
如果生物学差异本身就被误判成批次效应,校正就是帮倒忙。

我在项目中遇到过一位合作者,把肿瘤和正常样本分成两批测序,然后想用 ComBat 消除"批次差异"——结果肿瘤相关的基因一个都找不到了。
嗯,这就是典型的"不该校正却硬要校正"。

哪些情况必须校正

下面这些场景,我建议你果断上校正:

  • 批次与生物学因素正交——每个生物学条件在各批次里都有代表,而且比例接近。这时候批次效应就是纯噪音,去掉它只有好处。
  • 技术差异明显盖过生物学差异——比如 PCA 图上样本先按批次聚成一团,生物学分组完全打散。我在两个不同试剂盒建库的数据里见过这种情况,校正后分组才清晰起来。
  • 需要跨批次整合分析——比如你要合并公共数据库里的多个 RNA-seq 项目,不校正的话,差异表达基因里一半都是批次标记基因。
  • 批次内样本量充足——每批至少 3-5 个样本,校正方法才能稳定估计批次参数。

我的经验法则:如果 PCA/UMAP 上第一批样本和第二批样本各自抱团,而生物学分组在每批内部都能看出来——这就是典型的"该校正"信号。

哪些情况不能校正

这些时候,请你把手从键盘上拿开:

  • 批次与生物学因素完全混杂——比如第一批全是处理组,第二批全是对照组。你根本分不清差异是处理造成的,还是批次造成的。这时候校正会把生物学差异一并削掉。
  • 批次内只有单一生物学条件——每批只有一个组,校正方法会把这些组"拉到同一个平均值",真实差异直接归零。
  • 生物学差异远远大于技术差异——比如 knockout 和 wild-type 本身表达谱就天差地别,批次那点噪音根本不影响结论。校正反而可能引入假阴性。
  • 样本量太小——某批只有 2 个样本,校正方法对这批的估计几乎全靠先验,结果不可靠。

我曾经踩过的坑:处理一个 C. elegans 数据集时,年轻成虫和年老成虫分两批测序,批次与年龄完全混杂。我还是手痒跑了 limma::removeBatchEffect,结果差异基因从 2000 多个跌到 30 多个——全被校正"吃"掉了。后来重新设计实验,把两个年龄混样测序才解决问题。

决策流程:一张图说清楚

每次拿到数据,我会按下面这个流程走一遍。你可以直接把它贴在工位上。

批次效应校正决策流程 检查批次结构 PCA / 层次聚类 无显著批次效应 无需校正 存在批次效应 与生物因素混杂? 检查列联表 完全混杂 不可校正 可分离 技术差异主导? PCA 方差分解 技术差异 > 生物差异 需要校正 生物差异 > 技术差异 不应校正 💡 使用建议: 先将此流程写在实验记录本上。每次跑校正前,逐项检查,并截图保存 PCA 和列联表作为决策依据。 校正后务必验证:生物学差异是否保留?批次结构是否消失?

快速自查表

下面这个表格我经常在团队里用。拿到数据后,逐条对照,哪边勾选多就往哪边走。

✅ 需要校正的信号 ❌ 不应校正的信号
PCA 第一主成分对应批次 PCA 第一主成分对应生物学分组
批次内各生物学条件样本数均衡 某一生物学条件只出现在一个批次中
同一样本跨批次测序后聚类分离 批次与生物学分组完美对应(完全混杂)
差异表达分析中批次相关基因排名靠前 批次内样本量 ≤ 2
各批次技术指标(如 ERCC 内参)差异显著 生物学差异在跨批次比较中稳健一致

判断混杂程度的实操方法

别凭感觉判断"混杂不混杂"。我一般直接用列联表 + 卡方检验来说话。

# R 代码:检查批次与处理条件的混杂程度
library(NMF)

# 假设 colData 包含 batch 和 condition 两列
contingency_table <- table(colData(dds)$batch,
                           colData(dds)$condition)
print(contingency_table)

# 卡方检验
chisq.test(contingency_table)

# 如果 p < 0.05,说明批次与条件显著相关 —— 混杂了
# 如果 p ≥ 0.05,说明正交或接近正交 —— 可以校正

输出示例:

        condition
batch    control treated
  batch1      8       7
  batch2      8       9
  batch3      7       8

Pearson's Chi-squared test
X-squared = 0.143, df = 2, p-value = 0.931

# p = 0.93 → 完全正交,放心校正

如果看到下面这种表:

        condition
batch    control treated
  batch1     12       0
  batch2      0      11

Pearson's Chi-squared test
X-squared = 23.0, df = 1, p-value = 1.6e-06

# p < 0.001 → 完全混杂,绝对不能校正

小技巧:除了卡方检验,我还会用 table(batch, condition) / rowSums(table(batch, condition)) 看比例。某个条件在某批占比为 0% 或 100%,就是严重混杂。哪怕 p 值不显著,只要比例偏移超过 20%,我也会谨慎考虑校正的必要性。

避坑指南:三条铁律

最后分享三条用教训换来的铁律:

  1. 先绘图,再计算。 PCA 图能一眼看出批次和生物学分组的关系。如果 PCA 图上第一批和第二批完全分开,但每批内部两种条件混在一起——这是最理想的校正场景。如果第一批全是红色,第二批全是蓝色——别校正。
  2. 校正后必须验证。 我习惯校正完再画一次 PCA,检查批次是否混匀了,同时用已知的生物学标记基因看差异是否还在。如果标记基因的 p 值变大了很多,说明校正过度了。
  3. 不要盲目相信默认参数。 ComBat 的默认参数在样本量均衡时表现好,但如果某批只有 3 个样本而另一批有 30 个,我会手动调整 prior.plots 选项,或者改用 limma::removeBatchEffect 配合权重。

我曾经犯过的错误:有一回处理来自 4 个实验室的 RNA-seq 数据,批次与实验室完全对应。我以为用 ComBat 把"实验室效应"去掉就能合并分析。结果校正后,一批本该高表达的免疫基因在所有样本里都变成了中等表达——因为 ComBat 把每个实验室的基线拉平了,但这些实验室的样本本来就来自不同组织类型。后来我改用 RUVseq 用负对照基因估计未知因子,才保住了组织特异性信号。

总结一句话:校正不是默认选项,而是诊断后的处方。 先查结构,再判混杂,最后估量技术噪音与生物学信号的比值——这三步走完,你自然知道该不该按那个按钮。