跳转至

差异分析对比:DESeq2/edgeR/limma-voom

一句话概述:DESeq2是小样本的稳健首选,limma-voom在大样本和复杂设计中最灵活且FDR控制最好,edgeR是多因素实验和低丰度基因的中间选择——三者结果重叠度约90%,发表时建议多方法交叉验证。

核心知识点速查表

概念说明
DESeq2基于负二项分布的差异分析(白话:小样本最稳的方法)
edgeR基于负二项分布+经验贝叶斯(多因素灵活)
limma-voom微阵列线性模型+方差权重(大样本最快最稳)
负二项分布比泊松分布更适合RNA-seq计数(能处理过度离散)
离散度基因表达的变异程度(白话:同一个基因在不同样本间表达波动多大)
FDR假发现率,adj.p.value<0.05通常认为显著

一、三大工具对比

特性DESeq2edgeRlimma-voom
统计模型负二项GLM负二项GLM加权线性模型
标准化Median of RatiosTMMTMM+voom
离散度估计收缩估计(shrinkage)经验贝叶斯均值-方差趋势
最佳样本量n<10(★小样本)n=5-30n>20(★大样本)
FDR控制略保守可能膨胀最严格(★)
灵敏度高(低丰度好)中等(保守)
速度中等最快
复杂设计很好最好(★)
异常值处理自动检测需手动robust选项

二、R语言实操

2.1 DESeq2(小样本首选)

# === DESeq2 差异分析 ===
library(DESeq2)

# 从计数矩阵创建
dds <- DESeqDataSetFromMatrix(
  countData = count_matrix,               # 基因×样本的计数矩阵
  colData = sample_info,                  # 样本信息表(含分组)
  design = ~ condition                    # 实验设计公式
)

# 过滤低表达基因
keep <- rowSums(counts(dds) >= 10) >= 3   # 至少3个样本中计数≥10
dds <- dds[keep, ]

# 运行差异分析
dds <- DESeq(dds)                          # 一步完成:标准化+离散度+检验
res <- results(dds,
  contrast = c("condition", "Treatment", "Control"),  # 比较组
  alpha = 0.05                             # FDR阈值
)

# log2FC收缩(推荐,减少噪声)
res_shrink <- lfcShrink(dds,
  coef = "condition_Treatment_vs_Control", # 系数名
  type = "apeglm"                          # ★推荐的收缩方法
)

# 查看结果
summary(res)                               # 汇总统计
sig_genes <- subset(res, padj < 0.05 & abs(log2FoldChange) > 1)  # 筛选显著

2.2 edgeR(多因素设计)

# === edgeR 差异分析 ===
library(edgeR)

# 创建DGEList对象
dge <- DGEList(
  counts = count_matrix,                  # 计数矩阵
  group = sample_info$condition            # 分组信息
)

# 过滤低表达
keep <- filterByExpr(dge, group = dge$samples$group)  # 自动过滤
dge <- dge[keep, , keep.lib.sizes=FALSE]

# TMM标准化
dge <- calcNormFactors(dge, method="TMM")  # 计算标准化因子

# 设计矩阵
design <- model.matrix(~0 + condition, data=sample_info)  # 无截距设计
colnames(design) <- gsub("condition", "", colnames(design))

# 估计离散度
dge <- estimateDisp(dge, design)           # 估计离散度(common+trended+tagwise)

# 差异检验(准似然F检验,推荐)
fit <- glmQLFit(dge, design)               # 拟合模型
contrast <- makeContrasts(Treatment - Control, levels=design)  # 定义对比
qlf <- glmQLFTest(fit, contrast=contrast)  # F检验

# 查看结果
topTags(qlf, n=20)                          # 前20个差异基因
sig_edgeR <- topTags(qlf, n=Inf, p.value=0.05)$table  # 所有显著基因

2.3 limma-voom(大样本/复杂设计)

# === limma-voom 差异分析 ===
library(limma)
library(edgeR)  # 需要edgeR做TMM标准化

# 创建DGEList并标准化
dge <- DGEList(counts = count_matrix)
dge <- calcNormFactors(dge, method="TMM")

# 过滤低表达
keep <- filterByExpr(dge, group = sample_info$condition)
dge <- dge[keep, , keep.lib.sizes=FALSE]

# 设计矩阵
design <- model.matrix(~0 + condition, data=sample_info)
colnames(design) <- gsub("condition", "", colnames(design))

# ★ voom转换(关键步骤)
v <- voom(dge, design, plot=TRUE)           # 估计均值-方差关系
# 或用voomWithQualityWeights(处理异质样本)
# v <- voomWithQualityWeights(dge, design, plot=TRUE)

# 拟合线性模型
fit <- lmFit(v, design)                    # 线性拟合
contrast <- makeContrasts(Treatment - Control, levels=design)
fit2 <- contrasts.fit(fit, contrast)        # 应用对比
fit2 <- eBayes(fit2)                        # 经验贝叶斯调节

# 查看结果
topTable(fit2, n=20)                        # 前20个
sig_limma <- topTable(fit2, n=Inf, p.value=0.05)  # 所有显著

三、三方法交叉验证

# === 取三种方法的交集(更可靠) ===
library(VennDiagram)

# 提取各方法的显著基因(FDR<0.05, |logFC|>1)
deseq2_genes <- rownames(subset(res, padj<0.05 & abs(log2FoldChange)>1))
edger_genes <- rownames(subset(sig_edgeR, FDR<0.05 & abs(logFC)>1))
limma_genes <- rownames(subset(sig_limma, adj.P.Val<0.05 & abs(logFC)>1))

# 画韦恩图
venn.diagram(
  list(DESeq2=deseq2_genes, edgeR=edger_genes, limma=limma_genes),
  filename="DEG_venn.png",
  fill=c("red", "blue", "green"),
  alpha=0.5
)

# 取交集(最可靠的差异基因)
robust_DEGs <- Reduce(intersect, list(deseq2_genes, edger_genes, limma_genes))
cat("三方法交集基因数:", length(robust_DEGs), "\n")

四、可视化

# === 通用可视化 ===
library(EnhancedVolcano)

# 火山图(DESeq2结果)
EnhancedVolcano(res,
  lab = rownames(res),                     # 基因名
  x = 'log2FoldChange',                   # x轴
  y = 'padj',                             # y轴
  pCutoff = 0.05,                          # p值阈值
  FCcutoff = 1,                            # logFC阈值
  title = 'Treatment vs Control'
)

# MA图
plotMA(res, ylim=c(-5,5), main="MA Plot")

# 热图(显著基因)
library(pheatmap)
sig_matrix <- assay(vst(dds))[rownames(sig_genes), ]  # VST标准化
pheatmap(sig_matrix, scale="row",                       # 行标准化
         show_rownames=FALSE,
         annotation_col=sample_info["condition"])

五、面试高频考点

Q1: 三种方法该怎么选?

场景推荐原因
小样本(n<10)DESeq2离散度收缩估计最稳健
大样本(n>20)limma-voomFDR控制最好,速度最快
低丰度基因重要edgeR对低丰度转录本灵敏度更高
复杂实验设计limma-voom线性模型框架最灵活
不确定DESeq2最稳健的默认选择
发表论文三者取交集结果最可靠

Q2: 为什么不能直接用t检验?

  • RNA-seq数据是计数数据(离散,非正态)
  • 方差与均值不独立(均值越高方差越大)
  • 样本量通常很小(n=3),需要"借信息"估计方差
  • 白话:每个基因只有3个重复,直接t检验相当于只看3个人就下结论

Q3: voom做了什么?

  • 把计数数据转换为log-CPM(近似正态)
  • LOWESS拟合均值-方差关系
  • 给每个观测值一个精度权重(方差大的权重小)
  • 白话:voom告诉模型"这个数据点不太靠谱,别太相信它"

六、常见报错

报错原因解决
DESeq2: every gene contains at least one zero过滤不充分加强低表达过滤
edgeR: No residual df样本太少/设计矩阵有问题检查设计矩阵
voom: all zero counts某些基因全为0先过滤低表达基因
results: log2 fold change shrinkage正常提示使用lfcShrink

速查表

# === 差异分析速查 ===
# DESeq2
dds <- DESeqDataSetFromMatrix(counts, colData, ~condition)
dds <- DESeq(dds); res <- results(dds, contrast=c("condition","T","C"))

# edgeR
dge <- DGEList(counts); dge <- calcNormFactors(dge)
dge <- estimateDisp(dge, design); fit <- glmQLFit(dge, design)
qlf <- glmQLFTest(fit, contrast=con)

# limma-voom
v <- voom(dge, design); fit <- lmFit(v, design)
fit2 <- eBayes(contrasts.fit(fit, con)); topTable(fit2)

# 选择: 小样本→DESeq2 | 大样本→limma | 低丰度→edgeR | 发表→三者交集