第4章 数据获取与格式:Spaceranger输出解析、h5文件、MEX格式、AnnData对象

Pipeline跑完了,数据出来了。但你知道这些文件是干嘛的吗?

很多新手一上来就被一堆目录和文件搞懵了。明明跑成功了,却不知道从哪下手。我刚开始接触空间转录组时也这样——对着outs目录发了好几天呆。

这一章我们就来拆解Spaceranger的输出。弄清楚h5、MEX、AnnData这三种格式到底是什么关系。说白了,就是搞明白“数据在哪里、长什么样、怎么读进Python”。

4.1 Spaceranger输出目录结构

跑完Spaceranger count后,会生成一个输出目录。默认是你指定的--id参数值。我个人习惯先用tree看一眼整体结构:

tree -L 2 /path/to/sample_output/

你会看到类似这样的布局:

sample_output/
├── outs/
│   ├── filtered_feature_bc_matrix.h5
│   ├── filtered_feature_bc_matrix/
│   │   ├── matrix.mtx
│   │   ├── features.tsv
│   │   └── barcodes.tsv
│   ├── raw_feature_bc_matrix.h5
│   ├── raw_feature_bc_matrix/
│   ├── spatial/
│   │   ├── tissuelist.csv
│   │   ├── scalefactors_json.json
│   │   └── hires_image.png
│   ├── analysis/
│   └── web_summary.html
└── ...

核心数据都在outs/里。其中最重要的就是filtered_feature_bc_matrix——这是过滤后的表达矩阵。你想想看,后续所有分析都基于这个文件。

个人习惯:我一般先检查web_summary.html,确认质控指标没问题。然后再去碰矩阵文件。这样能快速定位问题,避免在错误的数据上浪费时间。

4.2 h5文件格式详解

h5格式是10x官方提供的单文件存储方案。它把矩阵数据、基因特征、barcode信息全塞进一个文件里。好处是方便传输和归档。

用Python读取非常直接:

import h5py

f = h5py.File("filtered_feature_bc_matrix.h5", "r")
print(list(f.keys()))
# 输出: ['matrix', 'matrix_features', 'matrix_barcodes']

# 查看矩阵形状
matrix_grp = f['matrix']
print(matrix_grp['data'].shape)
# 输出: (非零元素个数,)

里面包含三个主要组:matrix存的是稀疏矩阵的COO格式(data、indices、indptr),matrix_features是基因信息,matrix_barcodes是细胞barcode。

踩过的坑:我曾经直接拿h5文件里的data当成完整矩阵去算均值——结果算出来全是错的。那个data只存了非零值,必须还原成完整矩阵才能做统计。嗯,这里一定要注意。

4.3 MEX格式详解

MEX格式是Market Exchange Format的缩写。它用目录+三个文件来存储矩阵。相比h5,它更直观——你可以直接用文本编辑器打开看内容。

标准的MEX目录包含:

filtered_feature_bc_matrix/
├── matrix.mtx        # 稀疏矩阵,COO格式
├── features.tsv      # 基因信息(id、name、type)
└── barcodes.tsv      # 细胞barcode列表

matrix.mtx的内容长这样:

%%MatrixMarket matrix coordinate real general
33538 7864 12345678
1 1 5
1 2 0
2 1 3
...

第一行是注释,第二行是“基因数 细胞数 非零元素数”。后面每行是“基因索引 细胞索引 表达值”。注意索引是从1开始的。

用R或Python读MEX都很方便:

import scanpy as sc

adata = sc.read_10x_mtx(
    "filtered_feature_bc_matrix/",
    var_names='gene_symbols',
    cache=True
)

这一行代码就把整个矩阵读进来了。为什么推荐用sc.read_10x_mtx?因为它自动处理了索引偏移、基因名去重、barcode格式化。省心。

关键区别:h5是单文件,MEX是目录+三文件。h5适合长期存储和分发,MEX适合快速检查和处理。但在内存占用和读取速度上,两者几乎没有差别。

4.4 AnnData对象:统一的数据容器

在Python生态里,我们最终都会把数据转成AnnData对象。scanpy、squidpy、tangram这些工具全都围绕AnnData设计。它就像个“数据集装箱”——把矩阵、注释、空间坐标、图像全装在一起。

从h5或MEX转成AnnData非常简单:

import scanpy as sc

# 从MEX读取
adata = sc.read_10x_mtx("filtered_feature_bc_matrix/")

# 或者从h5读取
adata = sc.read_10x_h5("filtered_feature_bc_matrix.h5")

# 添加空间坐标
adata.obsm['spatial'] = spatial_coords  # numpy array, shape (n_cells, 2)

print(adata)
# 输出: AnnData object with n_obs × n_vars = 7864 × 33538
#       obsm: 'spatial'

AnnData核心结构就这几个:

  • X: 表达矩阵(默认是稀疏矩阵,节省内存)
  • obs: 细胞元数据(barcode、聚类标签、UMAP坐标等)
  • var: 基因元数据(基因名、高变基因标记等)
  • obsm: 细胞级多维矩阵(空间坐标、降维结果)
  • uns: 非结构化数据(配色、参数、图像)

我建议在数据读取阶段就直接转为AnnData。否则后面每换一个工具就要重新读一次数据,烦得很。

4.5 三种格式对比与选择建议

到底用哪种?我整理了一个表格:

维度 h5文件 MEX格式 AnnData对象
存储形式 单文件(二进制) 目录+3个文本文件 内存对象(可序列化)
可读性 需编程读取 可直接用文本编辑器查看 需在Python中查看
包含信息 矩阵+基因+barcode 矩阵+基因+barcode 矩阵+元数据+空间+分析结果
读取速度 快(二进制IO) 中等(文本解析) 取决于来源格式
适用场景 归档、传输、长期存储 快速检查、兼容老工具 分析全流程、多工具协作

我个人更倾向于这么用:原始数据用h5归档,日常分析用AnnData。MEX格式只在需要快速查看矩阵内容时才用。说白了,AnnData才是你真正干活时的核心。

避坑指南:我曾经在切换工具时,因为AnnData的var里基因名有重复,导致下游分析全乱套。建议读取后第一时间执行adata.var_names_make_unique()。就一行代码,能省你三天排查时间。
空间转录组数据格式流转关系 Spaceranger 输出 h5 文件格式 MEX 格式 AnnData 对象 下游分析流程 核心思路:Spaceranger 输出同时包含 h5 和 MEX 两种格式,最终都统一转为 AnnData 进行下游分析

到这,你应该对三种格式有了清晰的认识。从Spaceranger输出到AnnData,这条路其实很直接。记住一点就行:h5和MEX只是存储方式,AnnData才是你分析时的主战场。