第4章 数据预处理:质量控制、标准化、高变基因选择
数据预处理这一步,说白了就是给后面的分析“打好地基”。我刚开始做空间转录组项目时,总觉得数据拿到手直接跑聚类就完事了,结果跑出来的聚类结果一团糟——后来才明白,前处理没做好,后面再怎么调参数也是白费力气。咱们这一章就把 QC、标准化、高变基因选择这三个关键步骤拆开来讲,每一步我都会结合自己的踩坑经验给你说透。
4.1 为什么预处理这么关键
空间转录组数据有个特点:不仅维度高(几万个基因),还有空间坐标信息。如果原始数据里混着太多空液滴或死细胞,聚类结果就会把噪声当成真实信号。你想想看,一个只有20个UMI的点,它连基本的表达量都测不准,怎么能用来识别空间域?我个人的习惯是,预处理花的时间至少要占整个分析流程的30%,后面才能少走弯路。
咱们要做的三件事其实是一条流水线:
- 质量控制:剔除低质量的空间点(spots)
- 标准化:消除测序深度、点大小等技术偏差
- 高变基因选择:只保留信息量最大的基因用于聚类
4.2 质量控制(QC)
QC的核心目标就是识别并过滤掉“坏点”。空间转录组的每个点相当于一个“微组织样本”,它可能会因为组织褶皱、气泡、切片残片等原因质量很差。我常用的几个指标如下:
| 指标 | 典型阈值 | 说明 |
|---|---|---|
| UMI计数(nCount) | 500 ~ 20000(视组织类型调整) | 太低可能是空液滴,太高可能是重叠组织 |
| 检测基因数(nFeature) | 300 ~ 6000 | 低于300可能是空点,高于6000可能带气泡 |
| 线粒体基因比例(percent.mt) | < 20% | 超过20%提示细胞/组织可能已受损 |
实际做的时候,我会先用散点图把这三个指标的分布画出来,手动选一个“拐点”作为阈值。记住:没有一劳永逸的固定阈值,每个数据集都有自己的脾气。
# Seurat 中常用的QC代码片段(以空间数据为例)
library(Seurat)
library(SeuratData)
# 创建Seurat对象
st <- Load10X_Spatial("path/to/spatial/")
# 计算线粒体比例
st[["percent.mt"]] <- PercentageFeatureSet(st, pattern = "^MT-")
# 可视化QC指标
VlnPlot(st, features = c("nCount_Spatial", "nFeature_Spatial", "percent.mt"),
ncol = 3, pt.size = 0)
# 过滤
st <- subset(st, subset = nFeature_Spatial > 300 &
nFeature_Spatial < 6000 &
percent.mt < 20)
4.3 标准化
标准化要解决一个现实问题:不同空间点的测序深度可能差很大(比如有的点跑了5000 UMI,有的只有1000)。如果不做标准化,高深度点会被当成高表达,这显然不合理。
空间转录组最常用的标准化方法有:
- LogNormalize:每个点的UMI除以该点总UMI,再乘以缩放因子(默认10000),最后log1p。
- SCTransform:基于正则化负二项回归,效果更好,但计算量大。
- BayesSpace 自己的预处理:它推荐先用log(counts + 1)做简单标准化,再配合其内置的马尔可夫随机场建模。
我个人在BayesSpace流程中通常这样操作:
# 用 Seurat 完成标准预处理
st <- NormalizeData(st, normalization.method = "LogNormalize", scale.factor = 10000)
st <- FindVariableFeatures(st, selection.method = "vst", nfeatures = 2000)
st <- ScaleData(st)
# 这里ScaleData会把数据缩放到均值为0、方差为1,便于后续降维
4.4 高变基因选择
空间转录组数据通常检测到1~2万个基因,但其中大部分基因在点之间的表达变化很小,它们对区分空间域没有贡献。高变基因选择就是挑出那些“表现最活跃”的基因——它们在空间点上的表达水平波动最大。
常用方法有:
- 方差稳定变换(vst):Seurat默认方法,拟合基因均值-方差关系,挑选标准化后方差最大的基因。
- mean.var.plot:Seurat旧版方法,基于平均表达和方差绘制散点图。
- dispersion-based:基于离散度(如TPM高表达时方差更大)。
我一般选2000个高变基因,如果组织类型很单纯(比如正常脑组织),1500个也够;如果是肿瘤异质性很强的样本,可以加到3000个。选择太多会把噪声带进来,太少又会丢失信息。
# Seurat 中直接运行
st <- FindVariableFeatures(st, selection.method = "vst", nfeatures = 2000)
# 查看挑选的基因
top10 <- head(VariableFeatures(st), 10)
print(top10)
# 可视化高变基因
VariableFeaturePlot(st)
4.5 数据预处理流程概览
为了让你对整个流程有更直观的理解,我画了一张流程图,把三步串联起来:
可以看到,从原始数据到最终用于聚类的特征矩阵,每一步都有明确的输入和输出。我个人习惯是把这份流程固化成一个脚本,每次跑新数据前先跑一遍QC诊断图,确认无误后再走标准化和高变基因选择,这样能避免很多后期返工。
- QC阈值必须基于数据可视化手动确定,别用默认值。
- 标准化用log转换即可,不要额外做ScaleData(除非你知道自己在做什么)。
- 高变基因数量控制在1500~3000,优先检查线粒体基因占比。
做好了这三步,你的数据就已经准备好了。下一阶段我们就可以用它来运行BayesSpace的空间聚类算法了。不过在那之前,我建议你先拿这一套预处理流程跑一个简单的实例,感受一下每个参数变化对结果的影响——有时候“坏点”被过滤后,聚类的轮廓会变得清晰得多。