3、常见RNA-seq数据格式:FASTQ、SAM/BAM、counts矩阵、TPM/FPKM/RPKM
做RNA-seq模型验证,最怕什么?不是算法选不对,而是数据格式没搞懂。
我记得刚入行时,拿到一个10x的单细胞项目,同事扔给我一堆.bam文件。我直接当fastq读了……结果模型训了三天,出来的结果一塌糊涂。后来才发现,连数据是什么格式都搞错了。
所以这一章,咱们把RNA-seq常见的四种数据格式彻底讲清楚。你想想看,模型鲁棒性验证的第一步,就是确保你用对了数据。
3.1 FASTQ:原始序列的起点
FASTQ是测序仪直接输出的格式。说白了,它就是一段DNA序列,外加一个质量评分。每一个read都对应四行:
@SEQ_ID
GATTTGGGGTTCAAAGCAGTATCGATCAAATAGTAAATCCATTTGTTCAACTCACAGTTT
+
!''*((((***+))%%%++)(%%%%).1***-+*''))**55CCF>>>>>>CCCCCCC65
第一行是序列标识符(以@开头),第二行是碱基序列,第三行是分隔符(通常只有一个+),第四行是质量评分。
质量评分用的是Phred+33编码。每个字符对应一个ASCII码,减去33就是质量值Q。公式很简单:
Q = -10 * log10(P)
P = 10^(-Q/10)
Q30意味着碱基出错的概率是千分之一。我在项目中通常只看Q30的比例,低于80%的样本我会直接标记为高风险。
经验之谈:质量评分是RNASeq数据清洗的第一道坎。我曾经因为忽略接头上,导致下游比对率只有60%,白费了两周时间。建议每个样本先跑FastQC,检查GC含量、重复率、接头污染这些指标。
实测项目中,我习惯把所有FASTQ文件先合并统计,再看分布。如果某个样本的Q20比例低于50%,直接标记为异常,不参与后续模型验证。
3.2 SAM/BAM:比对后的标准格式
把FASTQ比对到参考基因组后,得到的就是SAM或BAM文件。SAM是文本格式,BAM是它的二进制压缩版。
比对文件长什么样?看这段示例:
@HD VN:1.6 SO:coordinate
@SQ SN:chr1 LN:248956422
@PG ID:bwa PN:bwa VN:0.7.17
read_1 0 chr1 10000 60 150M * 0 0 ATCGTAGCTA... IIIIIFFFFF... NM:i:0 MD:Z:150
每行代表一条read的比对信息。关键的字段包括:
- QNAME:read名称,要和FASTQ里的@行对应
- FLAG:一个整数,用位运算表示比对状态(比如是否配对、是否唯一比对)
- RNAME:参考序列名称(比如chr1)
- POS:比对起始位置
- MAPQ:比对质量,类似Q值,越高越好
- CIGAR:比对时发生的操作,如剪接、插入、删除
我常被问到:“SAM和BAM到底该用哪个?” 答案是:存储用BAM,调试用SAM。BAM体积只有SAM的1/5,而且samtools处理起来快很多。
注意:BAM文件必须排序和索引。未排序的BAM无法直接用于差异表达分析。我见过有人直接用未排序的BAM跑featureCounts,结果计数全乱了。一定要跑samtools sort和samtools index。
3.3 counts矩阵:基因表达的基本单位
把比对好的read映射到基因上,得到的就是counts矩阵。它是表达定量最原始的形式——每个基因有多少条read被检测到。
counts矩阵长这样:
gene_id sample1 sample2 sample3
ENSG000001.1 125 98 134
ENSG000002.2 0 1 0
ENSG000003.3 2367 2100 2456
每一行是一个基因(用ENSEMBL ID或基因名标识),每一列是一个样本,每个单元格是整数。
注意,counts矩阵的特点是整数,且服从负二项分布。这是后续差异表达分析的基础。多数工具(比如DESeq2)直接吃counts矩阵。
避坑指南:我曾经用FPKM矩阵跑DESeq2,结果差异基因一塌糊涂。因为DESeq2内部假设输入是整数counts,FPKM是小数,直接做归一化会破坏算法假设。所以从BAM到counts这一步,不能省。
生成counts矩阵的常用工具是featureCounts(subread包)和htseq-count。
featureCounts -T 8 -p -t exon -g gene_id \
-a Homo_sapiens.GRCh38.104.gtf \
-o counts.txt \
sample1.bam sample2.bam sample3.bam
这个命令会输出一个表格,包含每个基因在每个样本中的read计数。
3.4 TPM/FPKM/RPKM:归一化后的表达量
counts受基因长度和测序深度的影响,不能直接用来比较不同基因或不同样本的表达水平。所以需要归一化。
三种最常见的归一化方案:
| 指标 | 全称 | 归一化维度 | 特点 |
|---|---|---|---|
| RPKM | Reads Per Kilobase per Million | 基因长度 + 测序深度 | 最早出现,适用于单端测序 |
| FPKM | Fragments Per Kilobase per Million | 基因长度 + 测序深度 | RPKM的双端版本,考虑fragment |
| TPM | Transcripts Per Million | 基因长度 + 测序深度 | 先按长度归一化,再按比例缩放 |
它们之间的换算关系如下:
RPKM = (counts * 10^9) / (gene_length * total_reads)
FPKM = (fragments * 10^9) / (transcript_length * total_fragments)
TPM = (counts / gene_length) / sum(counts / gene_length for all genes) * 10^6
为什么我喜欢TPM?因为TPM在不同样本之间可比性最好。RPKM和FPKM对高表达基因有偏向,容易在跨样本比较时引入偏差。我在项目里,如果是做外部数据集评估,一律用TPM。
实操建议:
- 如果手里只有counts矩阵,用scaleCounts先转为TPM,再用于模型训练
- 如果已经是FPKM,可以通过公式反推出近似counts,但我建议直接拿原始的counts重算TPM
- 在做模型鲁棒性验证时,同时保留counts和TPM两份数据——counts用于统计检验,TPM用于表达量比较
知识体系梳理
四种格式在RNA-seq流程中的位置和关系,我用一张图来总结:
从图中能清楚地看到数据流向:测序仪出来是FASTQ,比对后变成SAM/BAM,定量后得到counts矩阵,再从counts计算归一化指标TPM或FPKM。
我建议做模型鲁棒性验证时,保留三条路径:
- 路径A:直接使用counts矩阵做差异表达分析
- 路径B:用TPM做跨样本标准化后的比较
- 路径C:用FPKM做原始长度的校正(如果外部数据集只有FPKM)
为什么留三条路?因为外部数据集质量参差不齐。有的公开数据只给了counts,有的只给了FPKM。掌握了这四种格式,你就能灵活应对各种情况。
最后提醒:千万别在模型输入里混用不同标准化的数据。比如训练集用TPM,测试集用FPKM,模型直接崩。一定要统一到同一个尺度。