跳到正文
百沐一下百沐一下
本节目录

edgeR、limma-voom、DESeq2 怎么选

跟完这篇,您能根据自己的样本量、数据类型和设计复杂度,在 edgeR、limma-voom、DESeq2 三者中选定一个(或干脆三个都跑),并在三者结果对不上时,按一张清单逐条排查,判断分歧是正常现象还是哪里出了错。

做 bulk RNA-seq 差异分析,绕不开这三个包。它们都久经检验、都靠得住,网上却常把「哪个更好」吵成玄学。其实选择没那么玄:它们的差别是统计模型适用场景的差别,对上您的数据就有答案。这篇不比高下,只给您一套可照着走的判断流程,外加一份把三个都跑通的最小代码。

一句话先分清三个工具

先建立整体印象,细节留到后面。

工具统计模型归一化一句话定位
DESeq2负二项 GLM,Wald 检验median-of-ratios上手最省心,小样本稳,结果表和收缩倍数都给全
edgeR负二项 GLM,准似然 F 检验TMM与 DESeq2 同源,小样本同样稳,QL 检验对假阳性控制好
limma-voom线性模型 + 精度权重,moderated t 检验TMM最快、对复杂设计最灵活,样本量大时尤其稳

三者都要原始 counts(非负整数),都不能喂 TPM、FPKM、RPKM。这一点没有例外——limma-voom 看似处理的是连续值,但它也是从原始 counts 出发、自己在内部完成归一化和转换的。为什么必须用原始 counts,见 counts、TPM、FPKM 怎么分

原理差异:它们在建什么模型

选工具之前,先弄清它们「算法上到底不一样在哪」,后面的取舍才不是背口诀。

DESeq2 和 edgeR 是一家人。 两者都把每个基因的 counts 看作服从负二项分布,用广义线性模型(GLM)拟合分组效应。counts 数据有个特点:均值越大、方差越大,负二项分布正是为这种「计数」量身定制的。它们最关键的共同点,是都用经验贝叶斯在成千上万个基因之间借信息来估计离散度(每个基因的变异程度)——这让它们在重复数很少时依然能给出稳健的方差估计。

两者的差别主要在细节:

  • 归一化不同:DESeq2 用 median-of-ratios,edgeR 用 TMM。思路相近,多数数据上结论接近。
  • 默认检验不同:DESeq2 默认 Wald 检验;edgeR 推荐 glmQLFit + glmQLFTest准似然(quasi-likelihood)F 检验,它把离散度估计的不确定性也算进去,对假阳性的控制通常更保守。

limma-voom 是另一条路。直接对 counts 建负二项模型,而是分两步:先用 voom 把 counts 变成 log-CPM,并根据均值—方差关系给每个观测值算一个精度权重(表达越低、越不可信的点权重越小);再把这些带权重的值喂给 limma 成熟的线性模型 + 经验贝叶斯 moderated t 检验框架。这套框架原本是为芯片数据打磨了多年的,好处是极快,且面对复杂设计(多因素、配对/区组、连续协变量、交互项)时写起来最灵活。

一句话记忆:DESeq2 / edgeR 直接对计数建模,小样本稳;limma-voom 转成连续值加权后建模,快且擅长复杂设计。

按样本量选

样本量是最实在的分岔点。下面的倾向是常见比较研究的大致共识,按数据调、不是硬阈值

  1. 每组重复很少(约 2~3 个):优先 DESeq2 或 edgeR。它们的经验贝叶斯离散度收缩在样本少时「借力」最明显,用极少的重复也能压住方差估计的噪声。这是它们最擅长的场景。
  2. 每组重复中等(约 5 个以上)到大队列limma-voom 越来越有优势。它快得多(几十上百个样本时差距明显),FDR 控制稳;相反,样本量很大时 DESeq2/edgeR 有时会偏激进(假阳性略多)。临床队列这类几十上百样本的场景,limma-voom 往往是稳妥之选。

几点提醒,避免把上面的话当铁律:

  • 这些倾向是统计性质上的平均表现,不是保证。在多数真实数据上,三者的 top 强信号基因高度重叠,分歧集中在临界区。
  • 无论哪个工具,每组只有 1 个样本都做不了差异分析(没有组内变异可估)。重复数太少时,增加重复永远比纠结换哪个工具更管用。
  • 需要复杂设计(多个协变量、交互、区组)时,无论样本量大小,limma-voom 的写法通常最省心,edgeR 的 GLM 通路次之。

按数据类型选

样本量之外,还要看数据本身是不是「计数」。选错这一步,模型的前提假设直接不成立。

您的数据该用什么别用什么
原始 counts(bulk RNA-seq、CRISPR 筛选、部分 counts 型测序)DESeq2 / edgeR / limma-voom 都行别喂 TPM、FPKM
已经是连续/对数强度(表达芯片、已 log 的定量蛋白/代谢组等)limma(普通 limma,可配 limma-trend别用 DESeq2/edgeR(负二项不适用),也别用 voom

要点就一句:负二项模型(DESeq2、edgeR)和 voom 都是为原始 counts 设计的;数据一旦本就是连续值或对数强度,改用普通 limma 直接建线性模型。 把 TPM 硬塞进 DESeq2,或把芯片强度当 counts 跑 edgeR,得到的 p 值都不可信。

三个都跑一遍(推荐做法)

拿不准哪个更适合时,最省心的办法是三个都跑,看结果重不重合。下面用同一份 counts(行基因、列样本)和同一个分组向量 group,给出三段最小可跑的骨架。为方便对齐,先统一把对照组设为参照水平。

group <- relevel(factor(group), ref = "control")   # 统一对照方向,treated 比 control

DESeq2

library(DESeq2)
colData <- data.frame(group = group, row.names = colnames(counts))
dds <- DESeqDataSetFromMatrix(counts, colData, design = ~ group)
dds <- DESeq(dds)
res_deseq <- results(dds, contrast = c("group", "treated", "control"))

edgeR(准似然,推荐)

library(edgeR)
y <- DGEList(counts = counts, group = group)
keep <- filterByExpr(y, group = group)      # 按惯例过滤低表达基因
y <- y[keep, , keep.lib.sizes = FALSE]
y <- calcNormFactors(y)                      # TMM 归一化
design <- model.matrix(~ group)
y <- estimateDisp(y, design)
fit <- glmQLFit(y, design)
qlf <- glmQLFTest(fit, coef = 2)             # 第 2 列 = treated vs control
res_edger <- topTags(qlf, n = Inf)$table

limma-voom

library(limma); library(edgeR)
y <- DGEList(counts = counts)
keep <- filterByExpr(y, group = group)
y <- y[keep, , keep.lib.sizes = FALSE]
y <- calcNormFactors(y)
design <- model.matrix(~ group)
v <- voom(y, design)                         # 转 log-CPM 并估计精度权重
fit <- lmFit(v, design)
fit <- eBayes(fit)
res_limma <- topTable(fit, coef = 2, number = Inf)

跑完取三者显著基因的交集,作为高置信集,通常比信任任何单个工具都稳:

sig_deseq <- rownames(subset(as.data.frame(res_deseq),
                             padj < 0.05 & abs(log2FoldChange) > 1))
sig_edger <- rownames(subset(res_edger, FDR < 0.05 & abs(logFC) > 1))
sig_limma <- rownames(subset(res_limma, adj.P.Val < 0.05 & abs(logFC) > 1))

common <- Reduce(intersect, list(sig_deseq, sig_edger, sig_limma))

这里的 padj < 0.05|log2FC| > 1(变化 2 倍)是常用惯例、不是铁律,要按数据和问题调,展开见 DESeq2 怎么做对 里的阈值一节。

三个结果对不上,先查什么

三者跑出来不完全一致,是常态,不是都得吓一跳。按下面顺序排查,能分清「正常分歧」和「真出错」。

  1. 先接受:它们本就不会逐基因完全相同。 模型和归一化不同,强信号基因通常高度重叠,分歧集中在临界区——padj 卡在 0.05 附近、低表达、低倍数的那些基因,排序会抖。这不是 bug。

  2. 确认您比的是「同一列」。 三个工具的显著性列和倍数列名字不一样,别把它们当算错了:

    工具校正后 p 值(FDR)log2 倍数变化
    DESeq2padjlog2FoldChange
    edgeRFDRlogFC
    limma-voomadj.P.VallogFC

    三者的 FDR 默认都用 BH 法校正,口径一致,可以直接横比。

  3. 输入是否一致。 是同一份原始 counts 吗?分组和对照方向(参照水平)是否一致?对照设反了,倍数变化会整体反号,看着就像两套结果。

  4. 过滤是否一致。 filterByExpr、手动 rowSums 门槛、DESeq2 的独立过滤,会让「进入检验的基因集合」不同,从而改变多重检验的分母、连带改变 padj。先统一过滤规则再比。

  5. log2FC 是否被收缩。 DESeq2 若跑了 lfcShrink,倍数会被往 0 拉;拿它和 edgeR/limma 的未收缩 logFC 直接比,会觉得「小了一截」。比较时两边都用未收缩的,或都用收缩后的。

  6. 归一化差异。 DESeq2 用 median-of-ratios、edgeR/limma 用 TMM,多数时候结论接近;但当个别样本存在极端高表达基因时,可能拉开差别。

  7. 样本量太小。 每组只有 2 个重复时,任何工具都不稳,三者对不上很正常。这种情况下别纠结换工具,补重复才是解法。

稳妥的收尾方式始终是:三者都跑、取交集当高置信集,单个工具独有的差异基因放到次要位置、留待验证。

在平台上跑一遍

不想在三个包之间反复配环境、对齐参数,可以在百沐一下直接做这一步:上传原始 counts 矩阵和样本分组表,用自然语言说清「哪组比哪组、对照是谁、样本量多大」,平台会零代码替您选定合适的方法跑完差异分析,并给出结果表和火山图;关键处(分组列、对照方向、过滤与阈值)它会先与您确认,选得不合适也能追问着改。

从上传到出结果的完整流程见 组学智能体使用指南,或直接开始:https://app.baimuyixia.com

相关