第2章:单细胞数据预处理:质控、标准化与整合基础

做单细胞分析的朋友都知道,拿到原始数据后第一步不是急着跑聚类或找 marker。你得先把数据洗干净。我个人习惯把预处理看成是给细胞做体检——不合格的细胞要剔除,信号要校准,不同批次的样本要能拉到一起比较。这套流程走顺了,后面的分析才不会翻车。

本章我们聚焦三个核心环节:质控(QC)、标准化(Normalization)和整合(Integration)。这三个步骤在批次效应诊断中是前置基础,也是你能不能在后续的 PCoA/UMAP 图上看出门道的关键。

2.1 质量控制:把好数据第一道关

质控说白了就是剔除那些「不健康」的细胞。你可能拿到 1 万个细胞,但里面混了不少空液滴、双细胞、或者快要裂解的烂细胞。如果不筛掉它们,后续的聚类和差异分析都会被污染。

我自己的标准流程一般看三个指标:

  • UMI 数量(nCount_RNA):太少可能是空液滴,太多可能是双细胞。
  • 检测到的基因数(nFeature_RNA):同样反映细胞复杂性。
  • 线粒体基因比例(percent.mt):超过 20% 通常说明细胞膜已破损。

⚠️ 注意:不同组织类型的阈值不一样。比如神经细胞线粒体比例天然偏高,而 T 细胞则偏低。我建议你先画分布图,用眼科观察 outliers 再去定阈值,别硬套文献里的数值。

# Seurat 标准质控流程
library(Seurat)

# 创建 Seurat 对象
pbmc.data <- Read10X(data.dir = "filtered_feature_bc_matrix/")
pbmc <- CreateSeuratObject(counts = pbmc.data, project = "pbmc3k", min.cells = 3, min.features = 200)

# 计算线粒体基因比例
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")

# 可视化 QC 指标
VlnPlot(pbmc, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3)

# 基于分布手动筛选
pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 20)

💡 我的习惯:先跑一个宽松的 QC(比如 percent.mt < 25%),做完标准化后再去看一次 QC 图。有时候标准化反而会放大某些批次效应,这时候再用更严格的条件回来过滤。

2.2 标准化:让细胞间可比

标准化要解决的是测序深度差异。有些细胞捕获了 10 万条 UMI,有些只有 1 万条,不代表它们生物学上有本质不同。我们得把每个细胞的总表达量拉到同一个基准线上。

最常用的方法是 LogNormalize,也就是先对每个细胞的 UMI 计数做总表达量归一化,再乘一个缩放因子(默认 10,000),最后做 log1p 转换。它简单、稳定,适合新手入门。

# 默认标准化
pbmc <- NormalizeData(pbmc, normalization.method = "LogNormalize", scale.factor = 10000)

# 等价于下面的手动操作(了解原理)
# norm_counts <- log1p(t(t(pbmc@assays$RNA@counts) / colSums(pbmc@assays$RNA@counts)) * 10000)

不过 LogNormalize 有个问题——它对高表达基因和低表达基因的方差影响不对称。做 PCA 的时候,高表达基因往往占主导地位。所以后来出现了 SCTransform,它用正则化负二项回归来建模 UMI 的均值和方差关系,可以更有效地去除技术噪音。

方法 核心原理 适用场景 速度
LogNormalize 总表达量归一化 + log1p 快速探索、小数据集 快
SCTransform 正则化负二项回归 大规模数据、批次结构复杂 稍慢
Pearson residuals 在 sctransform 内部使用 兼容下游 Harmony/CCA 整合 中等

✨ 个人建议:如果你的数据包含多个批次(比如不同病人或建库日期),直接上 SCTransform 是更稳妥的选择。我在项目中遇到过用 LogNormalize 后批次效应特别明显,换成 SCTransform 后 UMAP 图上批次直接混在一起了。

2.3 特征选择:找到最会「说话」的基因

标准化之后,我们通常需要选出一批 高变基因(HVGs)。这一步是为了降维做准备——你想想看,2 万个基因里有一半在不同细胞间几乎不表达或表达恒定,它们对区分细胞类型毫无贡献。不如只挑波动最大的 2000~5000 个基因来做 PCA。

Seurat 默认用方差稳定化变换(VST)来选择 HVGs,其实跟 SCTransform 的思路一脉相承。你直接运行下面的代码就行:

# 识别高变基因
pbmc <- FindVariableFeatures(pbmc, selection.method = "vst", nfeatures = 2000)

# 查看 top10 HVG
top10 <- head(VariableFeatures(pbmc), 10)
print(top10)

💡 避坑指南:我曾经做过一个免疫细胞数据集,默认 2000 个 HVGs 里几乎全是核糖体基因。这会导致后续聚类只看得到「核糖体高表达」与「低表达」的区别,完全掩盖了真正的细胞类型差异。解决办法是把核糖体基因从 VariableFeatures 中手动剔除。

2.4 整合基础:当数据来自多个批次

好了,现在你手上有两个样本:一个是健康人的 PBMC,一个是病人的 PBMC。你分别做了质控、标准化、找 HVG,然后把两个 Seurat 对象合并。结果一跑 UMAP——健康的和病人的完全分成两团。

是真的生物学差异吗?还是批次效应?老实说,单细胞整合就是为了解决这个「疑案」。

整合(Integration)是用来对齐不同批次间的联合嵌入空间,保留生物学差异的同时消除技术批次效应。目前主流的方法有:

  • CCA(Canonical Correlation Analysis):找批次间共有的基因-细胞相关结构,然后通过「锚点(anchors)」来校正。
  • Harmony:在 PCA 主成分空间上做软聚类和迭代校正,效率高、适合大规模数据。
  • scVI:基于变分自编码器的深度学习方法,适合复杂批次结构。

⚠️ 重要提醒:整合不等于「抹平所有差异」。当你的批次与生物学条件完全 confound(比如病人组都是第二批测的),整合可能会把真实的疾病信号也去掉。这时候需要结合实验设计来解读,不能无脑跑整合。

下面是一个用 Seurat CCA 整合的标准流程:

# 两个 Batch 对象拆分
pbmc.list <- SplitObject(pbmc, split.by = "batch")

# 分别标准化并找 HVG
pbmc.list <- lapply(pbmc.list, function(x) {
  x <- NormalizeData(x, verbose = FALSE)
  x <- FindVariableFeatures(x, selection.method = "vst", nfeatures = 2000, verbose = FALSE)
})

# 找到锚点并整合
anchors <- FindIntegrationAnchors(object.list = pbmc.list, dims = 1:30)
pbmc.integrated <- IntegrateData(anchorset = anchors, dims = 1:30)

# 整合后的数据存在 'integrated' assay 中
DefaultAssay(pbmc.integrated) <- "integrated"

# 标准化 + 降维 + 聚类
pbmc.integrated <- ScaleData(pbmc.integrated, verbose = FALSE)
pbmc.integrated <- RunPCA(pbmc.integrated, npcs = 30, verbose = FALSE)
pbmc.integrated <- RunUMAP(pbmc.integrated, reduction = "pca", dims = 1:30)

你看,整合后的数据在 'integrated' assay 里,而不是原始的 'RNA' assay。这里我建议初学者务必记住:差异表达分析应该回到 'RNA' assay 做,而可视化可以用 'integrated' assay。

2.5 本章知识体系总览

下面我用一张流程图把今天讲的内容串起来。这张图覆盖了从原始计数到整合数据的全流程,你在做自己的项目时可以直接照着思路走。

单细胞数据预处理全流程 原始计数矩阵 质量控制 nFeature / nCount / %MT 标准化 LogNormalize 或 SCTransform 特征选择 (HVGs) VST / dispersion / sct 1. 单样本 → PCA + UMAP 2. 多样本整合 选择整合方法 CCA / Harmony / scVI SRT / RPCA / scANVITI → 校正后降维 💡 核心判断准则 批次混在一起 → 可能是好的整合 生物学分组分开 → 保留真实信号

🎯 要点总结:预处理做得好,批次效应诊断就成功了 70%。不要跳过 QC 图,不要在没搞清楚批次结构之前就跑整合。稳扎稳打,把每一步的输出都可视化一眼——这点我反复在项目里强调。