分析结果不满意怎么追问迭代
跟完这篇,您能在结果已经跑出来之后,用「换阈值、换比较方向、改配色」这几类常见的追问,快速迭代出更合适的结果——而且大多数改动都不必从头重跑,几秒到几十秒就能看到新结果。
结果第一版几乎不会一步到位:阈值太松、方向反了、配色不好看、想少比一组……这些都很正常。新手最容易犯的错,是每改一点就把整条流程从原始数据重跑一遍,慢且容易出错。其实一条分析流程里,真正「贵」的只有一两步;只要把它们的中间结果存下来,后面的追问基本都是在便宜的步骤上重来。下面先给您一张「改哪儿要重算」的地图,再按最常见的三类追问逐一演示。
先把流程拆成四段:哪段贵,改哪段
把一条常规差异分析流程拆成四段,您就能一眼看出某个改动该动哪一段、要不要重算。越往下越便宜。
| 阶段 | 做什么 | 贵不贵 | 什么情况下才要重来 |
|---|---|---|---|
| 1 数据处理 | 读入矩阵、过滤低表达、归一化 | 中 | 换了样本或过滤规则 |
| 2 建模 | 拟合差异模型(DESeq()、estimateDisp() 等) | 最贵 | 改了设计公式,或改了纳入的样本 |
| 3 提取筛选 | 取结果表、按阈值挑显著基因 | 便宜 | 换阈值——只动这一段 |
| 4 出图 | 画火山图 / 热图 / 富集图,配色标注 | 最便宜 | 换配色、换标注——只动这一段 |
把这张表倒过来记更好用:您想改的东西越偏「展示」,代价越小。 大多数「不满意」其实落在第 3、4 段,根本不用碰最贵的建模。下面这张对照表把常见追问归了位:
| 想改什么 | 要不要重跑建模 | 改哪一段 |
|---|---|---|
| 换显著阈值(padj / log2FC) | 不用 | 第 3 段:在结果表上重筛 |
| 换比较方向(谁比谁) | 不用(用 contrast) | 第 3 段:重取一次结果 |
| 换配色 / 字号 / 标注 | 不用 | 第 4 段:在图上改样式 |
| 加批次或协变量校正 | 要 | 第 2 段:改设计公式后重跑 |
| 去掉离群样本 / 只留两组 | 要,但从子集重跑即可 | 第 2 段:子集后重跑 |
| 合并或重命名分组 | 要 | 第 1、2 段:改分组后重跑 |
换阈值:在结果表上重筛,不重跑
「显著基因太多 / 太少」是最常见的第一反应。这时不要重跑差异分析——阈值只是在已经算好的结果表上做一次筛选。
以 DESeq2 为例,建模只做一次,之后换多少套阈值都在结果表上重来:
library(DESeq2)
# 建模只做一次(这一步最贵)
dds <- DESeq(dds)
res <- results(dds)
res_df <- as.data.frame(res)
# 换一套阈值,就是换一次筛选,完全不碰上面的建模
up <- subset(res_df, padj < 0.05 & log2FoldChange > 1)
down <- subset(res_df, padj < 0.05 & log2FoldChange < -1)
nrow(up); nrow(down) # 看看上、下调各剩多少个
想放宽或收紧,只改数字再跑最后三行即可:
- 显著基因太少:把
padj < 0.05放宽到0.1,或把log2FoldChange阈值从1降到0.585(即 1.5 倍变化)。 - 显著基因太多、噪声大:反过来收紧,如
padj < 0.01。 - 常用组合是 padj < 0.05 配 |log2FC| > 1(2 倍变化)。这是常用惯例、不是铁律——效应弱的数据可放宽 log2FC,噪声大的可收紧 padj,按您的数据和生物学背景调。
一个容易混的点:事后筛选
abs(log2FoldChange) > 1,和在results(dds, lfcThreshold = 1)里对阈值做正式检验,不是一回事。前者便宜、常用,只是挑行;后者会重新计算 p 值、更严格。按需要选,别把两者当成同一件事。
一句提醒:反复调阈值直到「结果好看」,是选择偏差。阈值最好在看结果之前就按惯例定好;追问着换阈值,是为了做稳健性检查(换个合理阈值结论还成不成立),不是为了凑出显著。
换比较方向和分组:能省则省
「A 比 B」还是「B 比 A」、三组里只想看其中两组——这类分组层面的追问,有的免费,有的要重跑,但都比回到原始矩阵快。
换比较方向:不用重跑。 建好的模型里已经含了各组信息,换 contrast 重取一次结果就行,log2FC 的正负也随之翻转:
# 同一个 dds,取不同的两两比较,都不用重新建模
res_TC <- results(dds, contrast = c("condition", "treat", "control"))
res_XC <- results(dds, contrast = c("condition", "treat2", "control"))
用 contrast 明确写清「谁比谁」,还能顺手治好最常见也最尴尬的错误——方向读反。contrast = c("因子", "分子组", "分母组"),log2FC 为正即代表分子组更高。
只留两组、或去掉离群样本:要重跑,但从子集重跑。 数据变了就得重新建模,但不必回到原始文件,从已有的 dds 取子集即可:
# 只保留两组(或剔除某个离群样本),从子集重跑
keep <- dds$condition %in% c("treat", "control")
dds_sub <- dds[, keep]
dds_sub$condition <- droplevels(dds_sub$condition) # 去掉用不到的水平
dds_sub <- DESeq(dds_sub)
加协变量或批次校正:要重跑。 这改的是设计公式,属于第 2 段,必须重新建模:
# 把批次放进设计公式做校正,然后重跑
design(dds) <- ~ batch + condition
dds <- DESeq(dds)
调配色和样式:只动画,不动数据
「图不好看」几乎从不需要碰数据。配色、字号、标注都在第 4 段,改图就行。
火山图换配色,本质是先在结果表上按当前阈值打一列「类别」,再把颜色映射上去。换阈值只改判定那几行,换配色只改颜色向量:
library(ggplot2)
res_df <- as.data.frame(res)
# 按阈值分三类:上调、下调、不显著(改阈值只改这三行)
res_df$class <- "ns"
res_df$class[res_df$padj < 0.05 & res_df$log2FoldChange > 1] <- "up"
res_df$class[res_df$padj < 0.05 & res_df$log2FoldChange < -1] <- "down"
ggplot(res_df, aes(log2FoldChange, -log10(padj), color = class)) +
geom_point(size = 1) +
# 换配色只改这一行的取值
scale_color_manual(values = c(up = "#d62728", down = "#1f77b4", ns = "grey75")) +
theme_bw()
热图换配色和分组标注同理,只改对应参数,数据矩阵 mat 一动不动:
library(pheatmap)
ann_colors <- list(group = c(treat = "#d62728", control = "#1f77b4"))
pheatmap(mat,
scale = "row", # 按行 z-score,看相对高低
annotation_col = coldata,
annotation_colors = ann_colors, # 换分组配色只改这里
color = colorRampPalette(c("#2166ac", "white", "#b2182b"))(100)) # 换主色带只改这里
配色不只是审美——选对顺序、发散、定性三类配色,还要顾及色盲读者。挑色板和自查方法见 科研配色。
把中间结果存下来,才追问得动
上面所有「不用重跑」的前提,是那个贵的模型对象还在手边。把它存到硬盘,下次追问直接读回来,就能跨会话、跨天接着改:
# 算完就把贵的中间结果存下来
saveRDS(dds, "dds.rds") # 建好的模型
saveRDS(res, "res.rds") # 差异结果表
# 下次想追问,读回来接着改,不用从原始数据重跑
dds <- readRDS("dds.rds")
res <- readRDS("res.rds")
一套好用的迭代节奏:
- 一次性跑完到第 2 段:数据处理 + 建模,跑完立刻
saveRDS()存下dds。 - 把追问归类:先照第一张表判断,这次改动落在哪一段。
- 只动那一段往后:换阈值就从第 3 段重筛,换配色就从第 4 段重画,别回头动建模。
- 只有改了样本或设计公式,才重跑第 2 段,重跑完再存一次。
养成这个习惯,绝大多数「再看看换个阈值/换个配色的效果」都是几秒钟的事,您也就更敢多试几版、挑出最站得住的那一版。
在平台上跑一遍
这套「只重跑该重跑的那一段」的思路,正是百沐一下在做的事,而且不用您自己写代码存对象。结果出来后,直接用一句话追问就行——「把阈值放宽到 padj < 0.1」「只比较 treat 和 control 两组」「火山图换成蓝红配色」——平台会自动判断这次只需重筛还是要重画,保留能复用的中间结果,几秒返回新版本,并附上对应的可复现代码。做法见 智能作图使用指南 与 组学分析助手。