4、批次效应可视化:用眼睛发现批次结构

数据跑完了,差异基因也筛了,但总觉得结果不太对?别急着下结论。我个人习惯,拿到整合后的表达矩阵,第一步不是做差异分析,而是先画个散点图看看。批次效应这玩意儿,光靠统计指标不够直观,眼睛往往比任何检验都更早发现问题。

这一章咱们聊聊怎么用降维可视化来“看见”批次结构。说白了,就是给你的数据拍张合照,按批次涂上颜色——如果某几个批次的细胞各自抱团,那就是批次效应在作祟。

4.1 为什么可视化是批次诊断的第一站?

想象一下,你做了两个批次的实验,一个在A试剂,一个在B试剂。如果你直接把所有细胞混在一起分析,聚类结果很可能被试剂差异主导,而不是真正的生物学差异。可视化能让你在几分钟内判断:批次分离得有多严重?是全局偏移还是局部混淆?

常用的降维方法有三个:PCA、tSNE、UMAP。它们各有侧重,我一般这么用——先PCA快速扫一眼,再拿UMAP精细观察。tSNE呢?嗯,它计算慢、随机性大,我平时用得少,但有些人特别喜欢用它做最终展示图。

关键点:无论用哪种方法,必须按批次着色。否则你看到的任何结构都可能是伪迹。

4.2 PCA散点图——第一步诊断

PCA是线性降维,计算快,重现性好。我通常取前两个主成分(PC1 vs PC2),每个点代表一个细胞,颜色按批次标注。

举个代码例子(这里用Python的scanpy库,R的Seurat也类似):

import scanpy as sc
import matplotlib.pyplot as plt

# 读取数据,假设已合并
adata = sc.read("merged.h5ad")

# PCA计算
sc.tl.pca(adata, n_pcs=50)

# 画图,按批次着色
sc.pl.pca(adata, color="batch", title="PCA - Batch-colored")
plt.show()

画出来的图通常有两种情况:

  • 批次混合良好:不同颜色点相互交织,没有明显分群。
  • 批次分离明显:某个批次的细胞聚成一团,与其他批次隔开。这时候就需要做批次校正了。

我还记得有一次,PCA图上PC1和PC2刚好把两个批次分开,但PC3却显示出某个亚群的差异。这说明批次效应可能只影响少数维度,这时候只看前两个PC容易被骗。所以我也建议你多检查几个PC组合,比如PC3 vs PC4。

4.3 UMAP / tSNE——高维降维的细节

PCA看的是“大趋势”,但单细胞数据往往包含很多非线性结构。这时候UMAP和tSNE的优势就体现出来了——它们能保留局部邻域关系,把相似细胞拉得更近。

特征PCAtSNEUMAP
线性/非线性线性非线性非线性
速度快慢(尤其大样本)较快
重现性高低(需固定随机种子)中(受参数影响大)
对批次效应敏感性全局分离明显局部结构清晰兼顾全局与局部
参数敏感度低高(perplexity)中(n_neighbors, min_dist)

我个人强烈建议:先用PCA看全局,再用UMAP看细节。画UMAP时,一定要注意 n_neighbors 这个参数。我见过有人把这个值设成5,结果每个批次都碎成小团,看起来像完美分离——其实是过拟合了。默认15~30是个稳妥区间。

# 计算UMAP
sc.tl.umap(adata, n_neighbors=20, min_dist=0.3)

# 画图,按批次和生物学分组同时着色
sc.pl.umap(adata, color=["batch", "cell_type"], 
           wspace=0.5, title=["UMAP by batch", "UMAP by cell type"])

tSNE呢?我只有在数据量小于1万个细胞时才用它。而且一定要设置 random_state 或 seed,否则每次运行结果都不一样,无法复现。这是避坑指南里一定要写的:永远固定随机种子。

4.4 如何解读这些图?

画完图,看什么?我列个清单:

  1. 按批次着色,看分群:不同颜色是否各自成团?如果是,批次效应明显。
  2. 按细胞类型着色,看生物学信号:同一个细胞类型是否跨批次混合?如果是,说明整合效果不错。
  3. 检查离群批次:有没有一个批次完全脱离主体?可能是技术原因(如测序深度不同)。
  4. 对比校正前后:如果把校正前的图和校正后的图并排放置,能直观看到批次效应被消除。

警告:不要在UMAP/tSNE图上过度解读“小团块”。这些非线性方法会把随机噪声也放大。如果你看到一个只有3-5个细胞的“新群体”,先检查这是否是一个低质量的细胞簇(高线粒体、低基因数),或者是否来自同一个批次的单个样本。

4.5 常见陷阱(避坑)

画图本身不难,难的是不犯低级错误。我把自己踩过的坑分享给你:

  • 颜色盲:我曾经用红绿配色区分两个批次,结果合作者恰好是红绿色盲。现在我都用tab10或viridis色板,或者用形状/透明度辅助区分。
  • 忽略了杂乱的图例:批次太多时,默认图例挤成一团。记得调大legend_loc或单独保存图例。
  • 过度依赖tSNE的“云团”:tSNE的全局距离没有意义,两个远距离的团未必在生物学上不同。UMAP相对好一些,但也不完美。
  • 忘记检查PCA的载荷图:如果某些批次在PC1上分离,可以去看看是哪些基因贡献最大。有时候批次效应是由一两个高表达基因引起的。

一个小技巧:在Python里用sc.pl.pca(adata, color="batch")时,可以加参数show=False,然后plt.savefig("batch_pca.png", dpi=300),保存高清图方便汇报。

4.6 可视化流程总结

为了让你对整个可视化诊断流程有整体印象,我画了一张流程图:从原始数据到降维,再到按批次着色,最后判断是否需要校正。注意,这些步骤不是一次性的——你校正完应该再画一次,对比前后效果。

批次效应可视化诊断流程 原始表达矩阵 (基因×细胞,合并后) PCA降维 (前20~50个主成分) PCA散点图(按批次着色) PC1 vs PC2 vs PC3 UMAP / tSNE (n_neighbors, min_dist, perplexity) 评估:批次分离还是混合? 对比按细胞类型/生物学分组着色 ✅ 批次效应 → 校正 ✅ 混合良好 → 向下分析 参数注意 PCA: 标准化 UMAP: n_neigh=15~30 tSNE: perplexity=30~50 固定随机种子

这张图覆盖了核心流程:

  • 从合并后的表达矩阵出发,先做PCA(线性、快速)。
  • 然后分支到PCA散点图和UMAP/tSNE,两者各有侧重。
  • 最后综合判断:如果看到清晰批次分离,就需要进行批次校正;如果混合良好,就可以进入下游聚类和差异分析。

我的原则:校正前后各画一张图,放一起对比。如果校正后批次分离消失了,但细胞类型分群还在,才算校正成功。否则就得调参数或者换方法。