Bulk RNA-seq 分析入门(二):DESeq2 设计公式、对比与差异表达

Bulk RNA-seq 分析入门(二):DESeq2 设计公式、对比与差异表达
Perry上一篇把 FASTQ 处理到来源明确的计数或定量结果。这一篇往前走一步:如何从一个计数矩阵得到“比较了谁、考虑了什么因素、结果有多不确定”都能够说清楚的差异表达表?
本文只讨论 bulk RNA-seq,不是单细胞分析。本篇练习使用 Bioconductor airway 包附带的公开计数对象,不需要先下载原始 FASTQ。它包含四个气道平滑肌细胞来源的处理与未处理样本,适合演示配对关系。数据背景来自 airway 官方说明。这里学习统计流程,不将演示结果当成新的实验发现或医疗建议。
代码按 2026-10-06 核验的官方 API 组织,DESeq2 官方教程标注的包版本为 1.52.0。读者实际运行要记录自己的版本,不能只写“用了 DESeq2”。本机未执行下列 R 分析,因此本文不提供杜撰的差异基因数量、p 值或结果图片。
1. 先确认输入,而不是先调用 DESeq
最容易让整个分析失去意义的错误,是把样本标签与计数列错配。一个矩阵有六列,元数据也有六行,这只是尺寸相同,不是身份相同。必须先检查 ID 唯一、双方集合相同,再按 ID 重排,最后检查顺序完全一致。
第二个检查是输入单位。普通的计数矩阵入口要求非负、有限、整数的原始计数,不接受 TPM、FPKM、VST、rlog 或已经做过库大小缩放的数值。发现小数时应追问生成方法,不能为了通过构造函数而直接四舍五入。Salmon 估计计数的小数可以走 tximport 的专门入口,和 TPM 伪装计数不是同一回事。DESeq2 计数输入说明
第三个检查是元数据与实验设计。没有足够独立生物学重复、关键标签存疑或明显失败文库时,应暂停检验。已经知道的配对关系不能因为“不加这个变量也能跑”就忽略;batch 也不能因为 PCA 看起来有影响就随意追加,而应先追查真实实验记录以及它是否可与处理因素分别估计。
2. 设计公式是一张解释承诺,不是装饰
考虑三个原创的假设问题:独立来源的处理/对照比较可写 ~ condition;两组都分布在各批次且批次效应可估计时可写 ~ batch + condition;同一个来源各自提供处理与对照样本时可写 ~ subject + condition。这些公式回答的问题不一样,不能只以哪张火山图更漂亮为选择标准。
本篇的 airway 练习采用 ~ subject + condition,将来源之间的稳定差别和我们感兴趣的处理差别区分开。这个加性模型估计一个共同的处理系数,不估计来源与处理的交互;它不能证明各来源的真实效应相同,也不能涵盖所有重复测量问题。复杂时间序列、多层随机效应或处理交互需要另外设计模型;不要把两个条件的配对模板复制到所有实验上。DESeq2 官方配对与多因素分析入口
若所有对照都来自 B1、所有处理都来自 B2,那么 batch 与 condition 携带同一份分组信息。~ batch + condition 无法告诉我们变化究竟来自处理还是批次,这不是把 batch 变量删掉就解决了。设计矩阵的满秩检查可以发现不可分别估计的参数,但“满秩”也不保证混杂完全消失或样本量足够,只是必要的数学检查。
3. 完整练习:公开计数、配对模型与结果保存
运行前需要可用的 R 与相容的 Bioconductor 环境,并已经具备 airway、SummarizedExperiment、DESeq2、apeglm。本段检查依赖是否存在,不会自动安装。依赖缺失时先根据 Bioconductor 官方安装说明准备独立环境,确认安装权限、联网条件与版本兼容,再运行练习。
将下面代码保存为 airway_deseq2_learning.R,在自己的学习工作目录运行 Rscript airway_deseq2_learning.R。它只读取包自带的公开数据,在当前工作目录下创建一个带唯一名称的全新结果目录,不覆盖已有目录,也不会因 Rscript 退出而随会话临时目录消失。
1 | required <- c("airway", "SummarizedExperiment", "DESeq2", "apeglm") |
这里的预过滤规则是在最小条件组样本数那么多的样本中,计数至少为 10。它是为了教学声明的一种规则,不是所有物种、测序深度和实验的唯一正确选择,也不是先看对比结果再把不喜欢的基因删掉。保存的原始计数没有因过滤而消失,结果表则对应进入模型的基因。
运行结束后,结果目录保留在你启动 Rscript 时的当前学习工作目录里。保存打印出的完整目录路径,其中的 airway_bundle.rds 将作为下一篇的输入;不要移动或重命名后还使用旧路径。这里 tempfile() 只是生成一个未被占用的目录名称,实际位置明确指定为 getwd(),并非 R 会话自动清理的临时目录。
4. 如何读一行结果:效应与证据要分开
baseMean 描述归一化计数的平均水平;log2FoldChange 是该对比的效应估计;lfcSE 表达其标准误;stat、pvalue 和 padj 是相应统计检验与多重比较处理的产物。这里的方向固定为 treated 相对 control,正值表示模型下处理组更高,负值表示更低。将分子分母互换,效应符号随之改变,所以导出的表必须附有对比说明。DESeq2 结果字段手册
如果一个基因估计 log2FC 为 1,表示该模型中的相对倍数约为 2;这只是算术含义,不意味着这个基因一定显著,更不意味着它是整个表里最重要的基因。另一个基因可以有很小的效应,却因为信息更充分而得到较小 p 值。解释时应同时看效应、精度、表达水平和研究问题,而不是把单个数字当作综合评分。
padj < 0.05 是在特定模型、数据和假设下控制多重检验错误的一种判定规则,不是“这个基因有 95% 的概率是真的”,也不是任意一个选中基因有恰好 5% 假阳性概率。阈值之外的基因也不自动等于无变化。BH 等多重比较方法的定义可参阅 R 官方 p.adjust 文档。
5. shrink、筛选与效应阈值检验不是同一件事
当一个基因信息少或变异较大时,未经收缩的倍数估计可能很极端。lfcShrink 提供更稳定的效应估计,常用于可视化和效应排序。这不等于重新定义了本篇普通 Wald 检验的原假设,也不是把所有小效应变成“没有生物学意义”。本练习明确保留原检验的 pvalue/padj,另列 log2FC_shrunk,避免读者不知道某一列来自哪一步。收缩的模型依据可阅读 DESeq2 原始方法论文。
“普通检验 padj 小于阈值,并且收缩后绝对 log2FC 大于 1”可以作为声明过的候选展示规则,却不等价于已经检验“真实绝对效应大于 1”。若问题确实是超过一个预先指定的最小效应,应使用相应的效应阈值检验,例如:
1 | # 在完整练习后继续运行:检验 |log2FC| 是否超过预定阈值1。 |
默认 DESeq() 足够用于这个常规 bulk 学习入口。不要看到某篇单细胞性能教程,就盲目切换到 glmGamPoi 或同时改多项参数。任何拟合方式、离群值处理和阈值变更,都应说明对应的数据特征与验证依据,而不只是追求运行更快或基因更多。
6. Salmon 输入的替代入口:不把 TPM 当成计数
如果上一篇实际采用 Salmon 定量,建议从每样本 quant.sf 导入,而不是手动抽出 TPM 交给 DESeqDataSetFromMatrix()。下面是有真实文件之后的替代入口模板,不需要和 airway 练习同时运行。
1 | # metadata.tsv: first column sample_id; other columns include condition. |
这条路线通过完整对象向 DESeq2 传递估计计数与长度相关信息;不要又手动对矩阵做一次长度缩放,造成重复校正。countsFromAbundance 的不同选项有不同下游约定,本文只展示 no 加专门构造器的一条路线。转录本映射缺失、版本号不匹配、一个转录本映到多个基因等必须调查并记录;模板的结构校验不能替代参考来源审计。tximport 官方方法说明
~ condition 仅用于已经确认的简单独立设计。真实配对或批次实验应携带相应字段、检查设计并替换公式,不能因为换了导入入口就忘了配对关系。3′ 标签型 RNA-seq 的定量和长度处理也可能不同,应查相应协议,而不是把本模板视为所有 RNA 测序的标准答案。
7. 看到 NA 和报错,先判断原因
结果出现 NA,不应直接全部改为 1 或删除。全零、异常计数或独立过滤可能造成不同字段不可用,含义不一样。需要分别记录是否拥有检验 p 值和调整后 p 值,再按定义决定候选集或富集背景。报出非满秩时,优先检查完全混杂、没有样本的因子水平和冗余协变量,而不是不断删变量直到成功。
如果两组没有明确分开,也不要立即重做模型。样本差异可能主要由来源、细胞组成、时间或其他真实因素驱动。先回到原始 QC 与元数据,再解释探索图。计数模型加入 batch 与在展示图上去除 batch 是不同的事情;后一种视觉处理不能创造前一种设计里缺失的信息。
8. 本篇的自检与交付
在教学副本中,读入元数据后、按 ID 对齐之前插入 meta <- meta[rev(rownames(meta)), , drop = FALSE]。保留随后按 ID 对齐的那行时,顺序检查应通过,因为程序已经正确恢复匹配;再注释掉 meta <- meta[colnames(cts), , drop = FALSE],顺序检查才应阻止继续。这是在验证对齐逻辑,不是在修改真实分组。把 condition 的参考水平反过来,检查 resultsNames() 与你指定的对比方向有何区别。构造全部对照在 B1、处理在 B2 的元数据,检查设计矩阵秩,练习解释为什么这是设计问题。
正式交付至少应有输入来源、过滤规则、模型公式、参考水平、对比清单、完整结果表、NA 的处理说明、实际会话版本与 QC 记录。保留整张表,而不只保留显著基因;未来改变阈值或重查某个候选时,才不必依赖截图猜测。
上一章:实验设计、FASTQ 与计数;下一章:QC 图、功能富集与结果解释。

