第三章 创建Seurat对象:QC指标与过滤,标准化初步认识
好,我们正式开始动手。单细胞分析的第一步,就是把原始数据装进R里,弄成一个标准的Seurat对象。很多人觉得这步就是跑个函数,没什么技术含量。我早年也这么想,结果吃过不少暗亏。你想想看,数据本身质量不行,后面分析再花哨也是白搭。
说白了,Seurat对象就是个聪明的大容器。它能把表达矩阵、细胞元数据、基因信息、降维结果、聚类标签等等全塞在一起,而且每个部分还互相索引。你需要取某个基因在某个细胞里的表达量,一行代码就搞定。
3.1 从一个矩阵开始
我们先做一个小规模的演示。假设你从Cell Ranger或者STARsolo拿到了标准的三个输出文件:barcodes.tsv、features.tsv、matrix.mtx。读取并创建Seurat对象的经典操作如下:
library(Seurat)
# 读取10X标准输出
raw_data <- Read10X(data.dir = "path/to/your/filtered_feature_bc_matrix")
# 创建Seurat对象
sce <- CreateSeuratObject(
counts = raw_data,
project = "my_project",
min.cells = 3, # 至少在3个细胞中有表达的基因才留下
min.features = 200 # 至少检测到200个基因的细胞才保留
)
我个人习惯,min.cells设3,min.features设200,是前人总结的经验值,比较稳妥。如果你的数据测得很深,可以把min.features提到300甚至500,但初学阶段用默认就够。
CreateSeuratObject(counts = your_matrix)直接传入一个稀疏矩阵dgCMatrix,格式不对会报错。我踩过这个坑。
创建完对象后,你可以用sce看看它内部长什么样:
sce
# An object of class Seurat
# 2000 features across 100 samples within 1 assay
# Active assay: RNA (2000 features, 0 variable features)
看到这个结构,心里就有底了。但光有对象还不够,我们需要知道这些细胞的质量怎么样。
3.2 QC指标——好细胞长什么样
单细胞数据质量把控,我总结就三件事:
- 每个细胞检测到的基因数(nFeature_RNA)——太少可能是死细胞或空液滴,太多可能是双细胞或多细胞。
- 每个细胞的UMI总数(nCount_RNA)——与nFeature_RNA有正相关性,异常偏高可能是双细胞。
- 线粒体基因占比(percent.mt)——比例过高说明细胞膜破损,细胞质内容物泄露,线粒体基因相对富集。
计算线粒体占比,Seurat有现成函数:
sce[["percent.mt"]] <- PercentageFeatureSet(sce, pattern = "^MT-")
^MT-开头。小鼠是^mt-。斑马鱼、大鼠等物种的前缀不同,一定不要写错。我曾经一个项目,代码检查了三遍才发现物种前缀给用错了。
计算完后,用VlnPlot可视化,一眼就能看出离群点:
VlnPlot(sce, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)
这个箱线图+散点图的组合,我建议你保存一份。它是你最原始的数据快照,将来写论文汇报时总要用到。
3.3 过滤——做减法比做加法难
过滤看起来是剔除细胞,但目的其实是保留高质量的信号。常见的过滤标准如下表:
| 指标 | 常见下界 | 常见上界 | 说明 |
|---|---|---|---|
| nFeature_RNA | 200 | 5000 | 少于200个基因可能是空液滴;多于5000可能是双细胞 |
| nCount_RNA | 视测序深度而定 | 视测序深度而定 | 一般结合nFeature_RNA做散点图判断 |
| percent.mt | — | 20% 或 25% | 超过20%的细胞很可能已经破碎 |
实际操作时,我建议你对照VlnPlot的图形来定阈值,不要盲目套用别人的数字。过滤代码很简单:
sce <- subset(sce, subset = nFeature_RNA > 200 & nFeature_RNA < 5000 & percent.mt < 20)
做完这一步,你大概会剔除掉5%-15%的细胞数据集,具体看样本质量。我经历过一个肿瘤样本,坏死区域比例很高,mt占比超过50%的细胞占了近四分之一,那一刀切得我肉疼,但必须切。
3.4 标准化——让数据具有可比性
标准化是为了消除细胞间测序深度的差异。本来一个细胞测得深,基因表达量就高,但不代表它真的表达得多。你得把它拉到同一把尺子上。
Seurat默认的标准化方法是LogNormalize,但在我这门课——《SCTransform批次校正方法应用》里,我们要重点介绍SCTransform。SCTransform比传统方法好在哪里?它用一个正则化负二项回归模型,同时完成了标准化、方差稳定化和高变基因选择。一步到位,非常高效。
它的用法简洁到令人震惊:
sce <- SCTransform(sce, vars.to.regress = "percent.mt", verbose = FALSE)
vars.to.regress里加上批次变量,比如vars.to.regress = c("percent.mt", "batch")。我早期做多批次整合时就踩过一个坑,只在标准化后做校正,但批次效应在标准化前就已存在。SCTransform直接回归掉,效果立竿见影。
运行完成后,Seurat对象里会增加一个名为SCT的assay。后续的降维、聚类、差异分析都默认使用这个assay的数据。你不必再手动做一次FindVariableFeatures,因为SCTransform自动帮你选好了前3000个高变基因。
3.5 本章小结:一张图看懂流程
下面这张SVG图总结了从原始数据到Seurat对象、QC过滤、标准化的完整脉络。你可以把它当作一张检查清单。
走到这一步,你的Seurat对象已经干净、标准化,准备进入降维和聚类了。但别急,在进入那些性感的分析前,先花几分钟确认你的QC策略是否稳健。这是日后避免返工最有效的投资。