跳到主要内容

01 从数据到项目结构

这一章的目标是让读者在真正动手做 bulk RNA-seq 之前,先把"拿到什么输入、打算得到什么输出"想清楚。很多项目一开始跑得很顺,到了复盘阶段才发现样本表有问题、目录结构乱、中间文件丢了。bulk RNA-seq 的数据量比单细胞小得多,但分析链条更长,更值得一开始就把项目结构定下来。

一个典型项目的输入和输出

以最常见的两组比较为例:对照 vs 处理,每组 3 个生物学重复,每个样本一次双端测序。你手上会有的东西和最后要交付的东西大致是:

阶段输入输出
测序中心交付12 个 FASTQ 文件(6 样本 × 2 端)+ 基本 QC 报告
分析起点上面这些 FASTQ本地目录结构 + 样本表
比对 / 准比对FASTQ + 参考基因组 + GTF每个样本的 BAM 或 Salmon quant 目录
定量BAM / Salmon一份 gene × sample 的 counts 矩阵
差异分析counts + 样本表差异基因表(gene, log2FC, padj)
功能解释差异基因表GO / KEGG / GSEA 结果
交付所有上面的结果图 + 表 + Methods 段

"样本表"是整条链路的中心。它至少要有:样本 ID、条件、批次、测序时间、FASTQ 路径。后面每一步都要回到这张表。

项目目录

长期维护的目录结构没有标准答案,但至少应该满足"6 个月后回来还知道每个文件是什么"。一个可用的结构:

rnaseq_project/
├── README.md # 项目背景、样本来源、关键决策
├── metadata/
│ └── samples.tsv # 样本表,唯一可信来源
├── data/
│ ├── raw/ # 原始 FASTQ(不动)
│ ├── qc/ # FastQC + MultiQC 报告
│ ├── align/ # BAM 或 Salmon quant
│ └── counts/ # 合并后的 counts 矩阵
├── analysis/
│ ├── 01-qc.R
│ ├── 02-de.R # DESeq2 / edgeR
│ ├── 03-enrichment.R
│ └── 04-figures.R
├── results/
│ ├── tables/
│ └── figures/
└── envs/
└── env.yaml # conda 环境,锁定版本

几个经验:

  • data/raw/ 只读,永远不直接修改,新文件写到其他目录
  • 分析脚本按步骤命名(01-, 02-...),从上到下能复现整个流程
  • results/ 只放最终交付物,中间产物放 data/
  • envs/env.yaml 锁版本,过两个月再跑也能装回原环境

样本表怎么写

样本表是一个纯文本 TSV,越简单越好。一个最小可用版本:

sample_id condition batch r1 r2
CTRL_1 untreated 1 data/raw/CTRL_1_R1.fastq.gz data/raw/CTRL_1_R2.fastq.gz
CTRL_2 untreated 1 data/raw/CTRL_2_R1.fastq.gz data/raw/CTRL_2_R2.fastq.gz
CTRL_3 untreated 2 data/raw/CTRL_3_R1.fastq.gz data/raw/CTRL_3_R2.fastq.gz
TRT_1 treated 1 data/raw/TRT_1_R1.fastq.gz data/raw/TRT_1_R2.fastq.gz
TRT_2 treated 1 data/raw/TRT_2_R1.fastq.gz data/raw/TRT_2_R2.fastq.gz
TRT_3 treated 2 data/raw/TRT_3_R1.fastq.gz data/raw/TRT_3_R2.fastq.gz

batch 这一列不一定用得到,但有分析经验之后你会知道:一开始就记录下来是最便宜的,事后补很贵。测序批次、试剂批次、操作人、文库类型,只要是可能引入系统偏差的变量都值得留一列。DESeq2 的 design 会直接用到这些列:

design = ~ batch + condition

参考基因组和注释

人和小鼠的参考基因组有几个主流来源:

来源特点推荐用途
GENCODE人 / 小鼠注释的金标准绝大多数项目,和 Ensembl ID 对得上
Ensembl覆盖物种最多非模式物种
UCSC / NCBI字段丰富做浏览器可视化、变异分析

基因组和注释必须来自同一个来源、同一个版本,不然基因 ID 和坐标就对不上。推荐直接下载 GENCODE 的 primary assembly + 主注释 GTF,搭配 Salmon 或 STAR 都能跑:

# 人 v44 作为例子
wget -c https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/GRCh38.primary_assembly.genome.fa.gz
wget -c https://ftp.ebi.ac.uk/pub/databases/gencode/Gencode_human/release_44/gencode.v44.primary_assembly.annotation.gtf.gz

这两个文件解压后占 6~7 GB,落到 data/reference/ 里,长期项目里这份东西是共享的,不跟单个项目耦合。

比对 vs 准比对

两条主流路线:

路线典型工具速度磁盘适用场景
全比对到基因组STAR / HISAT2 → featureCounts大(BAM)需要 BAM 做可视化 / SNV / 新转录本
准比对到转录本Salmon / kallisto → tximport只做差异分析和富集

新项目如果只做差异表达和富集,用 Salmon 几乎是最佳选择 —— 笔记本上几分钟就能定量一个样本。下面这段是 Salmon 的典型调用:

# 建立索引(只做一次)
salmon index \
-t gencode.v44.transcripts.fa.gz \
-i salmon_index \
--gencode

# 定量每个样本
for s in CTRL_1 CTRL_2 CTRL_3 TRT_1 TRT_2 TRT_3; do
salmon quant \
-i salmon_index \
-l A \
-1 data/raw/${s}_R1.fastq.gz \
-2 data/raw/${s}_R2.fastq.gz \
-p 8 --validateMappings \
-o data/align/${s}
done

定量完成后每个样本会得到一个目录,里面的 quant.sf 就是转录本级别的定量结果。后续在 R 里用 tximport 聚合到基因级就进入差异分析:

library(tximport)
library(readr)

samples <- read.table("metadata/samples.tsv", header = TRUE, sep = "\t")
files <- file.path("data/align", samples$sample_id, "quant.sf")
names(files) <- samples$sample_id

# tx2gene 映射(从 GTF 生成一次就好)
tx2gene <- readr::read_tsv("metadata/tx2gene.tsv")

txi <- tximport(files, type = "salmon", tx2gene = tx2gene)
# txi$counts 就是 gene x sample 的 counts 矩阵

快速跳过:直接用 airway / pasilla

上面这套是面向真实项目的;如果只是想学习差异分析,完全可以跳过 FASTQ → BAM → counts 这一段,直接用 Bioconductor 已经打包好的 counts 数据:

  • airway — 人肺上皮 8 样本(4 对照 + 4 糖皮质激素处理),DESeq2 官方教程数据
  • pasilla — 果蝇 7 样本,DESeq2 最小例子

后面 020304 的真实示例都用 airway,装上包就能跑,不用碰比对流程。

下一步

参考资源

静态文件

离线资料下载

手册 HTML / PDF 已在后台预生成,点击后直接下载网站静态资源。