批次效应来源与检测:实验因素与可视化诊断
说到批次效应,很多新手会觉得这是个玄学问题。我最早接触它,是在一次单细胞测序项目中。两个样本明明是同一批细胞,只是因为第三天操作者换了一个人,结果出来,聚类图上两个样本分成了两团。你想想看,这不就是典型的批次效应嘛!
这一章,我们就来聊清楚批次效应到底从哪来,又该怎么发现它。我会从实验因素入手,再给你展示 PCA 和 UMAP 这两种可视化诊断手段。
批次效应的来源:实验因素
批次效应的本质,是实验过程中非生物学因素引入的系统偏差。说白了,就是你在操作、试剂、仪器上的一点小差异,被放大到了数据里。我个人习惯把来源分成四类,见下表:
| 来源类别 | 具体因素 | 典型场景 |
|---|---|---|
| 试剂批次 | 不同批号的抗体、酶、缓冲液 | RNA-seq 建库试剂盒换了批次,表达量整体漂移 |
| 操作者差异 | 不同人员的手工操作习惯 | 细胞计数、移液精度差异导致细胞数不一致 |
| 仪器平台 | 不同型号或校准状态 | 旧测序仪与新测序仪在 GC 偏好上有偏差 |
| 时间跨度 | 采样日期、存储时长、环境波动 | 早上采的样本和晚上采的样本代谢物谱不同 |
我在项目中遇到过最离谱的一次,是同一个样本的 RNA 建库,因为提前分装到两个不同管子,结果跑出来聚类图上两个样品不重叠。查了半天,原来一根管子离心管盖没拧紧——你看,物理隔离也能引入批次效应。
用 PCA 做初步诊断
PCA,也就是主成分分析。它的核心想法很简单:把高维数据投影到方差最大的几个方向。我习惯先用它做一个快速排查。
操作上,你只需要把样本按批次信息着色,看看同一批样本在散点图上是否聚集在一起。如果是,那批次效应就可能在作祟。
下面是一个典型的 PCA 扫描代码:
import scanpy as sc
import matplotlib.pyplot as plt
# 读取整合后的数据
adata = sc.read_h5ad('data.h5ad')
# 数据预处理
sc.pp.normalize_total(adata, target_sum=1e4)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000)
adata = adata[:, adata.var.highly_variable]
sc.pp.scale(adata, max_value=10)
# 执行 PCA
sc.pp.pca(adata, n_comps=30)
# 可视化,按批次着色
sc.pl.pca(adata, color='batch', show=True)
那 PCA 有没有盲区?有。我建议你别只看前两个主成分,也要看看前5个主成分的分布。有一次我遇到一个案例,前两个主成分显示批次分离不大,但到了第5个主成分突然分得很开。所以我的做法是,多看几张散点图。
用 UMAP 做精细解析
PCA 是线性方法,它能捕捉全局结构。但在很多真实场景中,批次效应是非线性的。这时候就要请出我们的第二个工具——UMAP。
你要知道,UMAP 和 PCA 不同,它更擅长保留数据的局部结构。说白了,它能更敏感地发现样本之间的细微差异。所以我个人的经验是:先用 PCA 快速排查,再用 UMAP 精细解析。
UMAP 也需要先基于 PCA 的结果来计算。直接对原始高维数据跑 UMAP 效果可能不好,因为邻居搜索在高维空间会失效(你想想看,维度灾难不是开玩笑的)。
代码示例如下:
# 基于 PCA 结果运行 UMAP
sc.pp.neighbors(adata, n_pcs=30, n_neighbors=15)
sc.tl.umap(adata)
# 可视化,按批次着色
sc.pl.umap(adata, color='batch', show=True)
UMAP 图上如果出现了明显的“条带”或“分区”现象,别犹豫——批次效应就摆在你面前了。
我曾经在一个整合项目中,PCA 看起来一切正常,批次样本混合得还不错。但我坚持跑了一个 UMAP,结果发现每一批样本在 UMAP 空间里都形成了一条细线。那怎么解释?本质上,每个批次内部的样本之间关系很近,但不同批次之间的距离被人为拉大了。这就是 UMAP 的敏感之处。
两种方法对比
为了让你更直观地理解这两个方法的差异,我整理了一张对照表:
| 维度 | PCA | UMAP |
|---|---|---|
| 建模方式 | 线性投影 | 非线性流形学习 |
| 对批次效应的灵敏度 | 全局结构,适合明显分离 | 局部结构,适合细微偏差 |
| 计算速度 | 快,适合大规模数据 | 略慢,依赖邻居计算 |
| 可视化效果 | 轴可解释 | 局部聚类清晰 |
| 典型用法 | 第一道排查 | 精细确认 |
本章知识体系
下面这张图总结了批次效应来源与检测的核心逻辑:
你想想看,如果连批次效应都没发现,直接去做差异分析,结果能靠谱吗?我以前就犯过这个错。当时拿到数据就直接跑差异,结果找出一堆“显著基因”——后来发现全是批次工造成的假阳性。那感觉,就像查了半天案子,最后发现是镜子里的自己。嗯,别提多尴尬了。
所以我的习惯是:每个项目开始前,至少花 15 分钟做一次 PCA + UMAP 的批次可视化检查。这一步花不了多少时间,但能帮你避免未来一个月的痛苦调试。你觉得呢?