4. 批次效应可视化:t-SNE/UMAP降维后按批次着色

说实话,处理批次效应的第一步,不是直接上矫正算法。

我个人习惯,先看数据长什么样。你想想看,如果你不知道问题的严重程度,你怎么知道该下多重的药?

这一章我们就来聊,怎么用t-SNE和UMAP这两个降维工具,把批次效应“画”出来。说白了,就是让数据自己说话,让你肉眼看到那些不该出现的批次分离。

4.1 为什么要先可视化?

数据是高维的。每个spot可能有几千个基因的表达值。你没法直接画个散点图来看。降维就是把这些高维信息压缩到2维或3维,保留最重要的结构。

我在项目中遇到过这样一个情况:一个同事花了三周跑各种矫正算法,结果效果还不如不矫正。为什么?因为他一开始就没看数据,其实那个数据集的批次效应根本不大,是他自己的预处理步骤出了问题。白费功夫。

所以,先可视化。这是避坑的第一步。

我的建议: 在运行任何批次校正算法之前,务必先做一次降维可视化。这能帮你快速判断:
1. 批次效应是否存在?
2. 效应有多强?
3. 是全局偏移还是局部扰动?
这个习惯,能帮你省下大量试错时间。

4.2 t-SNE vs UMAP:选哪个?

这两个都是非线性降维方法。但它们的脾气不太一样。

特性 t-SNE UMAP
速度 慢,尤其是数据量大时 快,通常比t-SNE快一个量级
全局结构保持 较差,更关注局部邻域 较好,能在一定程度上保留全局拓扑
可重复性 依赖随机种子,每次跑可能不同 相对稳定,不过也建议固定种子
批次效应敏感度 非常敏感,小差异也能放大 敏感,但不如t-SNE“夸张”
参数影响 perplexity值很关键 n_neighbors和min_dist影响大

我自己呢?在做批次效应诊断的时候,我通常两个都跑。t-SNE用来“找茬”,UMAP用来“确认”。t-SNE会把微小的批次差异放大,让你不容易漏掉问题。UMAP则给你一个更真实的全局视图。

注意: 千万不要只依赖t-SNE的可视化结果来做生物学结论。它擅长“聚在一起”,但距离和密度在t-SNE图上没有绝对意义。你看到的“分离”可能只是计算上的伪影。

4.3 具体怎么做?代码实战

好,我们来写代码。假设你有一个Seurat对象(R语言)或者anndata对象(Python)。我的示例用R语言的Seurat来演示,因为它在空间转录组社区用得很广。不过逻辑是一样的。

第一步,你要确保你的数据里已经包含了批次信息。通常这个信息在meta.data里,列名可能是"batch"、"sample_id"或者"orig.ident"。

# 假设你已经有一个Seurat对象: spatial_obj
# 检查批次信息
head(spatial_obj@meta.data)
# 应该能看到一列叫 "batch" 的列

第二步,降维。如果你还没跑PCA,得先跑。t-SNE和UMAP通常基于PCA的结果来做。我个人习惯用前30个PC。

# 标准化和PCA
spatial_obj <- NormalizeData(spatial_obj)
spatial_obj <- FindVariableFeatures(spatial_obj)
spatial_obj <- ScaleData(spatial_obj)
spatial_obj <- RunPCA(spatial_obj, npcs = 30)

# 跑UMAP
spatial_obj <- RunUMAP(spatial_obj, dims = 1:30)

# 跑t-SNE (可选)
spatial_obj <- RunTSNE(spatial_obj, dims = 1:30)

第三步,才是我们的重头戏——按批次着色绘图。

# 按批次着色看UMAP
DimPlot(spatial_obj, reduction = "umap", group.by = "batch") +
  ggtitle("UMAP colored by batch")

你看,就这么简单。几行代码,图就出来了。但重点是怎么看这张图。

4.4 怎么读图?—— 三看原则

图出来之后,别急着下结论。我总结了一个“三看原则”,照着做就行。

  1. 一看分离度:
    不同颜色的点是不是明显分开了?如果是,恭喜你,批次效应很严重。
    比如,所有红色的点挤在左上角,所有蓝色的点挤在右下角。中间没有一个重叠。
    这就是典型的“完美分离”。你需要矫正。
  2. 二看重叠度:
    不同颜色的点是不是混在一起?但混得“不自然”?
    举个例子:红色的点在某个区域占主导,但蓝色点也零星有一点。或者不同批次形成了“条带状”的结构。
    这就是部分重叠,部分分离。也属于需要关注的情况。
  3. 三看混合度:
    理想状态下,不同批次的点应该在UMAP空间里均匀混合。就像一个搅拌均匀的沙拉,分不清哪片生菜来自哪棵菜。
    如果看起来是这样的,那你的数据可能本身批次效应就很小,或者你的实验做得非常棒。
关键: 判断是否需要矫正,不是看“有没有分离”,而是看“分离的程度是否远大于生物学差异”。如果不同批次对应不同的生物学区域(比如不同的组织切片位置),那它们本来就应该分开。我见过有人把部位差异当成了批次效应,结果一矫正,把真实的生物学信号给抹平了。这是大坑。

4.5 避坑指南:我踩过的那些雷

我曾经犯过一个低级错误。跑完UMAP,看到不同批次完美分离,激动得不行,赶紧跑矫正。结果发现矫正后数据一团糟。后来检查,发现是我在ScaleData的时候,没有按批次进行回归,导致技术差异被放大了。嗯,这个坑不小。

这里我列出几个常见问题,你遇到了可以对照看看。

  • 问题1:PC选少了。
    只用前5个PC,可能导致信息丢失,批次效应不明显。
    建议: 至少用20-30个PC。我通常用30个。
  • 问题2:Perplexity设错了(t-SNE)。
    t-SNE的perplexity值如果太小,点会很分散,看起来像是都有差异;如果太大,所有点会挤成一团。
    建议: 对于空间转录组数据,我一般设perplexity在30-50之间,然后微调。
  • 问题3:忽略了生物学变量。
    别忘了,有些差异是生物学差异。如果你把不同解剖区域的样本放在一起,它们本来就不该重叠。
    建议: 同时按生物学分组(比如“区域”、“细胞类型”)着色,对比看看。如果批次和生物分组高度相关,那情况就比较复杂了。
批次效应可视化诊断流程 1. 数据准备 2. 降维 (PCA → UMAP / t-SNE) 3. 按批次着色 3. 按生物学变量着色 4. 对比:批次 vs 生物学分离模式 5. 决策:是否需要矫正? 确保 meta.data 包含批次列

这张图把流程捋清楚了。核心就是对比例子:看看批次分离的模式,是不是和生物学分离的模式一致。如果一致,那可能不是批次效应,而是你想找的那个生物学差异。

4.6 进阶:定量评估批次效应

视觉判断有个问题:主观。不同人看同一张图,可能得出不同结论。而且图有时候会骗人,尤其是当数据量很大的时候。

所以我有时候会用几个量化指标来辅助判断。虽然这些指标不完美,但可以作为参考。

  • LISI (Local Inverse Simpson's Index):
    这个指标衡量局部邻域的“混合度”。如果LISI值高,说明局部区域混合得好。如果低,说明同一批次占主导。
    可以用lisi包来计算。
  • kBET (k-nearest neighbor Batch Effect Test):
    它检查每个spot邻域内的批次比例是否与全局批次比例一致。不一致,就说明有批次效应。
    可以用kBET包。
  • Silhouette Score:
    经典的聚类评估指标。如果按批次聚类后轮廓系数高,说明批次区分度大,效应强。
我的建议: 不要完全相信任何一个量化指标。它们都有假设条件。比如LISI假设样本混合均匀,如果数据本身有结构(比如不同的组织区域),那LISI值低可能只是因为生物学结构,而不是批次效应。所以,量化指标要和可视化结合着看,相互验证。

4.7 一个小结

批次效应可视化的核心,就三件事:降维、着色、对比。工具就那几个,没什么花哨的。重点在于你怎么读图,怎么判断。

记住,你的目标是区分“技术噪音”和“生物学信号”。可视化是第一步,也是最容易出问题的一步。图做得好看不难,但看得准,需要经验积累。

嗯,这一章就到这里。后面我们会进入真正的校正环节,但请记住,没有这个诊断步骤,后面的校正就是“瞎搞”。