4、数据加载与QC:把原始数据变成干净的单细胞对象
终于到了动手的环节。单细胞分析的第一步,就是把测序仪输出的原始数据,塞进Seurat对象里。这一步做不好,后面所有分析都会歪。我见过太多人跳过QC直接跑聚类,结果画出来的UMAP图全是垃圾……说白了,数据加载和质控才是整个流程里最值得花时间的步骤。
4.1 读取10X Genomics标准输出
10X Genomics的数据,最常见的是Cell Ranger管道输出的三个文件:
barcodes.tsv.gz
features.tsv.gz
matrix.mtx.gz
Seurat提供了专用函数 Read10X(),一行搞定:
library(Seurat)
# 假设数据在 "filtered_feature_bc_matrix/" 目录下
counts <- Read10X(data.dir = "filtered_feature_bc_matrix/")
# 创建Seurat对象
pbmc <- CreateSeuratObject(counts = counts, project = "PBMC_4k")
你想想看,为什么用 filtered_feature_bc_matrix 而不是 raw?因为Cell Ranger已经帮你把空液滴和死细胞过滤了一次。但别完全信任它,二次QC还是必须的。
gene.column = 2。
4.2 读取其他格式的数据
不是所有数据都来自10X。H5格式、CSV、甚至h5ad(Scanpy输出)我都遇到过。这里给几个常用方法:
| 数据格式 | 推荐方法 | 说明 |
|---|---|---|
| 10X H5(单个文件) | Read10X_h5() |
直接读取filtered_feature_bc_matrix.h5 |
| CSV/TSV 矩阵 | ReadMtx() |
需要barcodes和features文件 |
| H5AD(Scanpy输出) | ReadH5AD() |
需安装hdf5r包,常用于跨平台合作 |
| 10X v2/multiome | CreateSeuratObject() + 手动拼接 |
有时features文件列名不一致,需调试 |
举个例子,读取一个商业平台输出的CSV文件:
expr_matrix <- read.csv("counts.csv", row.names = 1)
obj <- CreateSeuratObject(counts = expr_matrix, project = "custom_data")
dim() 和 head() 检查原始矩阵。
4.3 计算QC指标:线粒体、基因数、UMI数
Seurat对象创建后,会自动计算两个基本指标:nCount_RNA(每个细胞的UMI总数)和 nFeature_RNA(每个细胞检测到的基因数)。但我们一般再加一个:线粒体基因比例。为什么?细胞破裂或凋亡时,线粒体RNA会因为没有核膜保护而大量释放,导致比例异常高。
计算线粒体比例的方法:
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
注意,人类用 ^MT-,小鼠用 ^mt-。如果你在用斑马鱼或其他物种,得先看一眼线粒体基因的前缀。
我觉得这一步最容易出问题的是:版本差异。老版本Seurat里 PercentageFeatureSet 第二个参数叫 features,新版本改成了 pattern。如果你查旧代码直接复制,可能会报错。
三个核心指标我们要重点看:
- nCount_RNA:UMI总数。太低说明细胞捕获失败或空液滴;太高可能是双细胞或技术异常。
- nFeature_RNA:检测到的基因数。同样,太低是死细胞/空液滴,太高可能双细胞。
- percent.mt:线粒体比例。一般死细胞超过10-20%就要警惕。
怎么观察?画小提琴图:
VlnPlot(pbmc, features = c("nCount_RNA", "nFeature_RNA", "percent.mt"))
一般来说,一眼就能看出异常尾巴。我习惯把三个图叠加在一起,先看整体分布,再定阈值。
4.4 质控过滤:设定阈值
阈值没有绝对标准,取决于组织类型和实验条件。这里给一份我在PBMC数据集上常用的参数做参考:
| 指标 | 典型阈值 | 逻辑 |
|---|---|---|
| nFeature_RNA | 200 ~ 2500 | 低于200可能是空滴或死细胞,高于2500可能是双细胞 |
| nCount_RNA | 不设上限,但结合基因数看 | 如果UMI很高但基因数很少,说明技术噪声 |
| percent.mt | < 20%(严格时< 10%) | 超过20%基本是垂死的细胞 |
过滤代码:
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 20)
实际项目中,我还会额外检查doublet得分(用DoubletFinder等工具),但那是后面的内容了。对于基础QC,上述过滤就够了。
4.5 本章知识框架图
为了让你一眼看清整个流程,我画了一张SVG图:从原始数据到干净对象的每一站。
整个流程并不复杂,但每一步的决策都会影响最终结果。我自己的经验是:先快速画一个粗略的QC图,选好阈值后再做一次精细过滤。别一次性把参数定死,灵活调整才能适应不同数据。