2. RNA-seq 数据基础:从 FASTQ 到 count 矩阵
拿到 RNA-seq 项目,第一件事不是跑 DESeq2,是先把原始数据变成 count 矩阵。
没有 count 矩阵,后面所有差异分析和标记筛选都是空谈。
这一章,我就带你走一遍这个标准流程。
说白了,RNA-seq 数据分析有三个核心步骤:
- 原始数据:测序仪下机的 FASTQ 文件
- 比对/定量:把 reads 定位到参考基因组或转录本
- count 矩阵:汇总每个基因被多少条 reads 覆盖
2.1 FASTQ 文件,长什么样?
FASTQ 是测序仪最原始的产出格式。
每条 read 有 4 行:
@EAS139:136:FC706VJ:2:2104:15343:197393 1:Y:18:ATCACG
GTGCTTGCATCTGATCTGCTGTGCCTGACCGTCAGTGTGTG
+
BBBB@B@BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
- 行 1:序列标识符,@ 开头
- 行 2:碱基序列
- 行 3:分隔符,通常就一个 +
- 行 4:质量评分,每个字符对应一个 Phred 分数
我的一点习惯:拿到新项目,我会先跑一遍 FastQC 看看质量分布。有一次项目数据质量很差,3' 端全是低质量碱基,如果不提前修剪,后面比对率会非常低。
注意:FASTQ 的质量编码有 Phred+33 和 Phred+64 两种。现在绝大多数数据是 Phred+33,但老数据可能是 +64。FastQC 能自动识别,不过如果你写脚本自己解析,一定要确认。
2.2 比对,到底比到哪?
有两种主流策略,我个人都接触过,各有适用场景。
| 策略 | 代表工具 | 输出 | 典型场景 |
|---|---|---|---|
| 有参比对到基因组 | STAR、HISAT2 | BAM 文件 | 有高质量参考基因组 |
| 直接定量到转录本 | Salmon、kallisto | 量化的 count/TPM | 速度快,无需完整基因组 |
STAR 是我用得最多的比对工具。它的核心是「种子搜索 + 拼接」两步,速度非常快。
一个典型命令长这样:
STAR --genomeDir /path/to/genome_index \
--readFilesIn sample_R1.fastq sample_R2.fastq \
--outFileNamePrefix sample_ \
--outSAMtype BAM SortedByCoordinate
如果你用 featureCounts 做定量,它会直接读取 BAM 文件,统计落到每个基因外显子区域的 reads 数量。
命令非常简单:
featureCounts -T 8 -t exon -g gene_id \
-a annotation.gtf \
-o counts.txt \
sample_sorted.bam
-T 8 用 8 个线程,-t exon 指定统计 exon 特征,-g gene_id 按基因 ID 汇总。
一个坑:featureCounts 默认用 --primary 只统计 primary 比对。我曾经遇到过一批 BAM 文件没经过 properly paired 过滤,结果计数偏高。后来加上了 -s 0(不区分链)重新跑才正常。
2.3 count 矩阵的三种生成方式
我把它分成三类,你根据项目情况选一个就行。
方式一:HTSeq-count
Python 写的,基于 GTF 注释,逐条 reads 判断落在哪个基因上。
htseq-count -f bam -r pos -s no \
sample_sorted.bam \
annotation.gtf > sample_counts.txt
-s no:不区分链特异性-r pos:BAM 已按位置排序- 优点是结果稳定,缺点是速度慢
方式二:featureCounts
subread 包里的 C 程序,速度比 HTSeq 快很多。
featureCounts -T 4 -t exon -g gene_id \
-a annotation.gtf \
-o all_counts.txt \
sample1.bam sample2.bam sample3.bam
一次跑多个样本,输出一个合并的 count 矩阵。
我的建议:项目样本数超过 20 个,我肯定选 featureCounts。HTSeq 在样本少、需要仔细排查比对质量时用。
方式三:STAR --quantMode GeneCounts
STAR 在比对的同时可以直接输出 count 数量,不需要额外工具。
STAR --genomeDir index \
--readFilesIn R1.fastq R2.fastq \
--quantMode GeneCounts \
--outFileNamePrefix sample_
它会生成一个 ReadsPerGene.out.tab 文件,第四列是 unstranded 的 count。
三种方式对比:
| 工具 | 速度 | 内存 | 多线程 | 多样本合并 |
|---|---|---|---|---|
| HTSeq-count | 慢 | 低 | 否 | 需手动 |
| featureCounts | 快 | 中等 | 是 | 一次性输出 |
| STAR GeneCounts | 极快 | 高 | 是 | 每样本独立文件 |
注意:STAR 的内置定量模式没有多映射 reads 的校正。如果你的项目是重复序列富集的物种(比如植物),我还是建议用 featureCounts 配合 -M --fraction 参数。
2.4 从多个样本到一张 count 表
无论用哪个工具,最终要得到一个矩阵。行是基因 ID,列是样本名,单元格是整数。
一个标准的 count 表长这样:
gene_id control_1 control_2 treatment_1 treatment_2
ENSG000001 120 145 200 180
ENSG000002 50 60 22 30
ENSG000003 900 850 1100 1050
注意:count 必须是整数,不能是归一化值。DESeq2 自己会做内部归一化,所以给原始整数就行。
一个实用操作:featureCounts 输出文件第一行以 # 开头,第二行是列名。导入 R 时用 read.table(..., skip=1) 跳过注释行。
# R 代码示例
counts <- read.table("all_counts.txt", header=TRUE, row.names=1, skip=1)
counts <- counts[, -c(1:5)] # 去掉注释列,只保留 count 列
2.5 本章小结
好了,你应该清楚了:
- FASTQ 是原始数据,要检查质量
- 比对或定量是关键步骤,STAR + featureCounts 是经典组合
- count 矩阵是 DESeq2 的输入基础