第2节:批次校正方法概览——ComBat、Limma、RUV、SVA 该怎么选?
当你拿到一批跨越不同测序批次或实验日期的组学数据,第一件事就是问自己:我看到的差异,到底是生物学信号,还是批次引入的噪音?
这节我们不搞长篇理论推导,直接摊牌——四种主流校正方法,它们各自擅长什么、怕什么、适合处理什么类型的数据。我会结合自己踩过的坑来聊,希望能让你少走弯路。
四个方法的「身份证」
先上一张表格,把核心差异排出来。后面我们再逐个展开。
| 方法 | 核心假设 | 需要什么信息 | 最大优势 | 最大短板 |
|---|---|---|---|---|
| ComBat | 批次效应是位置+尺度变化 | 已知批次标签 | 稳定、好用,效果公认 | 假设分布形式固定(正态) |
| Limma | 线性模型可以吸收批次 | 已知批次标签 | 灵活,可同时考虑多个协变量 | 适合微阵列,RNA-seq需转logCPM |
| RUV | 有「负对照基因」来估计噪音 | 负对照基因集或重复样本 | 不需要知道批次怎么分的 | 对照基因选不好就翻车 |
| SVA | 未知的、隐性的批次因子 | 不需要批次标签 | 发现你不知道的批次效应 | 容易把生物学信号一起干掉 |
ComBat:行业老大哥,最稳的起手式
ComBat(Combating Batch Effects)是我个人最常用的方法——没有之一。它来自 Johnson 等人 2007 年的论文,距今快二十年了,但依然是大多数 RNA-seq 集成分析的首选。
它到底在算什么?
ComBat 假设:每个基因在批次之间,均值和方差都会偏移。它用经验贝叶斯方法,把每个批次的均值「拉回」基准水平,同时把方差也整容一下。
一句话总结:如果你有明确的批次标签(比如 Batch_1, Batch_2),并且批次数量不太少(>= 3 个批次效果更好),直接用 ComBat 通常不会出错。
我的习惯:先跑一次 ComBat,然后做 PCA 看批次是否混在一起。如果混得很好,就不再试别的了。我曾在一个 8 个批次、600 个样本的 RNA-seq 项目里这么干,效果肉眼可见。
# R 代码示例:sva 包中的 ComBat
library(sva)
adjusted_data <- ComBat(
dat = expression_matrix,
batch = batch_vector,
mod = model_matrix_for_biological_covariates,
par.prior = TRUE,
prior.plots = FALSE
)
要注意什么?ComBat 假设表达值近似正态分布。如果数据是原始的 count 矩阵,记得先做一步转化(比如 log2(CPM + 1))。
我曾经踩过的坑:直接在原始 count 上跑 ComBat,然后差异分析的结果全变了。后来发现 ComBat 对低表达基因的方差调整非常敏感,一定要先过滤掉那些在一半以上样本里都没表达的基因。
Limma:线性模型的老手,小样本的救星
Limma 本是一个差异表达分析的工具包,但它有个很聪明的用法:把批次效应作为协变量放进线性模型里一起拟合。
Limma 的做法是「吸收」而不是「校正」。它不改变表达矩阵本身,而是在回归系数估计阶段把批次项的贡献「扣掉」。说白了,如果你最终的差异分析也要用 Limma,那一步到位最省事。
它特别适合什么场景?
- 样本量极小(比如每个条件只有 3 个样本)
- 批次和生物学因素有部分重叠(此时 ComBat 可能过度校正)
- 你本来就要用 Limma 做差异分析,顺手的事
# R 代码示例
library(limma)
design <- model.matrix(~ 0 + condition + batch)
fit <- lmFit(expression_matrix, design)
# 在对比矩阵里不需要考虑 batch 项
contrast_matrix <- makeContrasts(
"treatment - control",
levels = colnames(design)
)
fit2 <- contrasts.fit(fit, contrast_matrix)
fit2 <- eBayes(fit2)
我个人建议:如果你处理的是微阵列数据,或者 RNA-seq 数据量较小(比如几十个样本),优先试 Limma。它不会动你的原始数据,出问题也好排查。
RUV:当你连批次怎么分的都不知道时
RUV(Remove Unwanted Variation)来自 Gagnon-Bartsch 等人 2013 年的工作。它的思路完全不一样:我不需要你告诉我哪一列是批次,我只要一组「应该不受生物条件影响」的基因,就能反推出批次噪音。
这个「负对照基因」怎么找?
- 在你的数据里,找那些在所有样本中表达量几乎不变的基因(比如看变异系数)
- 或者用 spike-in 探针(ERCC 等)
- 或者用「假基因」、「持家基因」等
RUV 的几个变体:
- RUVg:基于负对照基因估计
- RUVs:基于重复样本(不要求有对照基因)
- RUVr:基于残差估计(适合没有对照基因也没有重复设计的情况)
我曾经遇到的教训:选负对照基因时,我偷懒直接用所有低表达基因,结果 RUV 把真实的生物学差异也「校正」没了。负对照基因的核心是稳定且与生物学条件无关,不是随便找一堆低表达的就完事。
SVA:发现隐藏的魔鬼
SVA(Surrogate Variable Analysis)是这四种里「脑洞最大」的一个。它不要求你已经知道批次是什么,而是通过奇异值分解(SVD)之类的技术,从数据中自行推断出「隐藏因子」。
想象一下:你的实验设计里只写了 Batch_1 和 Batch_2,但实际上因为一个操作员的手抖,Batch_2 的前 10 个样本和后 10 个样本的室温差了 2 度。这种隐藏的批次,只有 SVA 有可能发现。
但它有代价——
- 如果你不知道自己在做什么,SVA 可能把生物学信号的一部分也认定为「隐藏因子」并去除
- 它对强信号非常敏感,如果有一个处理效应特别明显,SVA 可能优先捕获到它,然后...你懂的
我的经验:SVA 适合在探索性分析中使用。先跑一次 SVA,看看它找到了几个隐藏因子。如果因子数远大于你的批次数,说明你的实验可能有你没意识到的变异来源。这时候不要盲目校正,先搞清楚原因。
方法选择的决策流程图
下面是我根据自己的项目经验,整理出的一个快速决策流程。你可以把它当「菜单」来用。
这张图是我在实际项目中反复调整后固化下来的。基本上,从左上角开始,一一回答框里的问题,就能找到最适合你当前数据的方案。
还有一个「隐藏考点」:不要依赖单一指标
你可能会想:那我跑完校正,是不是看 PCA 图里批次混到一起就说明对了?
不完全对。PCA 只是可视化。如果批次被「暴力」拉到一起,也可能把真实的信号拉乱了。我记得有一次项目,PCA 图漂亮得不行,结果差异分析出来一个显著的基因都没有——那说明校正过于「强硬」了。
我个人的检查清单:
- PCA / t-SNE 图:批次混合度是否改善?
- 生物学差异:已知阳性对照基因是否还在?
- 差异分析结果:校正前后 DE 基因数量变化是否合理?
- 可视化检验:每个基因的箱线图,看批次间分布是否对齐。
总结
四种方法没有绝对的「谁更好」,只有「谁更合适」。ComBat 是稳妥的默认选择,Limma 适合小样本和微阵列,RUV 在你没有批次标签但有对照基因时是神器,SVA 用来发现你不知道的坑。
建议你从 ComBat 开始,如果结果不满意或数据特殊(比如没有批次标签),再考虑 RUV 或 SVA。当然,如果你还没开始做差异分析,把 Limma 一步到位也是一个很省心的选择。
一个小提醒:别忘了在做批次校正之前,先保存一份原始表达矩阵的备份。我见过有人直接在原始数据上覆盖校正结果,后来想重新来过都没办法。嗯,这种事,发生过不止一次。