单细胞RNA-seq数据基础:读入原始数据格式
做单细胞分析,第一步就是把手头的原始数据读进来。我刚开始接触这个领域时,面对一堆文件后缀完全摸不着头脑——.mtx、.barcodes.tsv、.features.tsv、.h5ad……到底哪个才是正经数据?
其实说白了,单细胞转录组数据的核心就一个东西:cell × gene 矩阵。行是细胞,列是基因,每个格子告诉你某个基因在这个细胞里有多少个UMI(或count)。后面所有的聚类、差异分析、批次校正,全是在这个矩阵上做文章。
嗯,咱们先看两种最常见的原始数据格式:10X 格式和 h5ad 格式。
10X 格式:三个文件一个也不能少
10X Genomics 平台产出的数据,通常会给你一个文件夹,里面至少三个文件:
| 文件名 | 作用 |
|---|---|
matrix.mtx(或 matrix.mtx.gz) | 存储稀疏矩阵格式的计数数据,只记录非零元素 |
barcodes.tsv(或 barcodes.tsv.gz) | 每个细胞对应的barcode序列,一行一个 |
features.tsv(或 genes.tsv) | 基因标识符,通常包含两列:基因ID和基因名 |
注意:这三个文件的名字不能自己乱改,必须严格对应。我早期有个项目,团队把文件改了名,结果 scanpy.read_10x_mtx 死活报错,查了半天才发现文件名不匹配。避坑指南:保持原始命名,或者用软链接。
读入代码很简单:
import scanpy as sc
adata = sc.read_10x_mtx(
'./data/filtered_feature_bc_matrix/', # 包含三个文件的目录
var_names='gene_symbols', # 用基因名作为变量名
cache=True # 缓存加速多次读取
)
这里 var_names='gene_symbols' 的意思是,用 features.tsv 第二列的基因符号作为列名。如果选 gene_ids,就会用第一列的ENSEMBL ID。我个人习惯用基因符号,因为后续做可视化直接显示基因名,不用再映射。
h5ad 格式:一步到位
如果你拿到的是 .h5ad 文件,那就更省事了。h5ad 是 AnnData 对象的原生存储格式,里面已经包含了细胞×基因矩阵、细胞元数据、基因元数据,甚至降维结果。读入只有一行:
adata = sc.read_h5ad('./data/pbmc3k_processed.h5ad')
为什么会有两种格式?实践中,10X 格式是测序公司的标准产出版本,而 h5ad 更多是分析流程中保存中间结果用的。比如我用 scwrite(adata, 'my_data.h5ad') 存下来,下次直接读,免去重复预处理。
读入之后,先看看矩阵长什么样
无论哪种格式,读进来都是 AnnData 对象。里面的核心是 X 属性,就是那个 cell × gene 矩阵。我来展示一下怎么检查:
print(adata.shape) # (细胞数, 基因数)
print(adata.X) # 稀疏矩阵,默认是 csr_matrix
我见过不少新人把矩阵打印出来看,结果因为稀疏矩阵里全是0,吓一跳以为数据丢了。其实单细胞矩阵极度稀疏——通常 90% 以上的格子都是0。用稀疏格式存储,内存能省几十倍。
cell × gene 矩阵到底是什么?
这个概念我画了一张图,你一看就明白:
关键理解:矩阵中的数值是原始的UMI计数,不是归一化后的表达量。后续我们会做标准化、对数化,但那是后面的章节。现在只需要确保你读进来的矩阵,能正确对应到细胞和基因。
实战:检查读入数据的完整性
我建议你每读入一个数据集,先跑一遍下面这个检查清单:
adata.X的类型是csr_matrix吗?(如果不是,考虑转换:adata.X = adata.X.tocsr())adata.obs_names有没有重复?adata.var_names有没有重复?- 总count的分布是否合理?
sc.pp.sum(adata, total='counts_per_cell')看看 - 基因是否包含线粒体基因、核糖体基因(后续质控要用)
有一次我在一个公共数据集上遇到 adata.var_names 里出现了NA,一查发现 features.tsv 第三行是空基因名。我当时没检查,结果后面画图时基因名全是 NA 搞得一头雾水。所以现在每次读数据,我都会用 print(adata.var.head()) 扫一眼。
两种格式的对比
| 对比维度 | 10X 三文件格式 | h5ad 格式 |
|---|---|---|
| 读入函数 | sc.read_10x_mtx | sc.read_h5ad |
| 文件数量 | 至少3个(.mtx, .tsv ×2) | 单个文件 |
| 读取速度 | 稍慢(需解析多个文件) | 较快,直接读取 |
| 是否包含元数据 | 仅矩阵和标识 | 可包含 obs、var、uns 等全部内容 |
| 适用场景 | 测序公司直接产出,最原始 | 流程中保存中间/最终结果 |
避坑指南:千万不要用 pandas.read_csv 去读 .mtx 文件!那是稀疏矩阵格式,不是文本表格。一定要用专门的读取函数。我曾经见过同事试图用Excel打开 matrix.mtx,结果计算机直接卡死——文件虽然小,但行数动辄几十万。
小结
这一章的核心就两件事:读入 和 验证。读入用 sc.read_10x_mtx 或 sc.read_h5ad,验证用 .shape 和 print(adata)。理解 cell × gene 矩阵是后续所有分析的基础,把这个概念印在脑子里,后面讲质控、归一化、降维你都不会跑偏。