4. 主成分分析(PCA)检测批次效应:原理、PCA图解读、颜色编码

好,咱们终于到了重头戏:怎么用主成分分析(PCA)来揪出批次效应。

之前我们聊过批次效应的危害,也铺垫了探索性数据分析的思路。现在,就是亮出真家伙的时候了。

我个人特别喜欢PCA。它就像一把万能钥匙,能打开高维数据的大门,让你一眼看清数据的整体结构。想当年我接手一个癌症转录组项目,样本来自三个不同医院的测序中心,当时我心里就犯嘀咕:这数据能直接合在一起分析吗?结果PCA一跑,好家伙,三个医院的数据在PC1上分得清清楚楚,批次效应直接“怼”到了脸上。

PCA检测批次效应的核心逻辑

说白了,PCA就是给数据“降维”。

想想看,我们手里的基因表达矩阵,动辄两万个基因。人脑是没法直观理解20000维空间的。PCA呢,它就像变魔术一样,找到数据变异最大的方向,然后把这些方向投影到一个二维或三维的平面上。

它的核心逻辑可以拆成三步:

  1. 找方向: 找到数据点方差最大的那个方向,叫第一主成分(PC1)。
  2. 再找方向: 在跟PC1垂直的方向里,再找方差最大的,叫第二主成分(PC2)。
  3. 画投影: 把所有的样本点都画到PC1和PC2构成的坐标系里。

批次效应为什么能在PCA图上被看到?因为批次之间的人为技术差异,通常会引入很大的系统变异。这个系统变异,如果比真实的生物学差异还大,那它就会被PCA抓住,并体现在前几个主成分中。

核心思想: PCA并不“知道”有批次效应,它只是忠实地展示了数据最大的变异来源。如果批次标签在PCA图上聚成一团,说明批次变异已经压制了生物学变异。这就是我需要警惕的信号。

PCA检测批次效应:从高维到二维的逻辑流程 输入数据 (基因×样本矩阵) 数据标准化 (中心化 + 缩放) 协方差矩阵 (计算特征向量) PC投影:选取PC1、PC2 (降维到2D,捕获最大方差) 可视化:PCA散点图 + 按批次着色 批次1聚类 批次2聚类 批次3聚类 批次间差异大 = 批次效应严重 样本交叉混合 = 批次效应小

PCA图解读:到底在看什么?

当你拿到一张PCA图,别急着下结论。先问自己三个问题:

  • 样本是按已知生物学分组聚类的吗? 比如癌症vs正常,治疗vs对照。如果是,那恭喜,生物学信号很强。
  • 样本是按批次标签聚类或分层的吗? 如果同一批次的样本像串葡萄一样挤在一起,而不同批次之间隔得老远,那就有问题了。
  • 前几个PC解释的方差比例高吗? PC1解释了30%还是80%?如果PC1就解释了大几十的方差,往往意味着有一个巨大的主导因素在起作用。这个因素可能就是你不想看到的批次。

我遇到过一种情况:PC1解释了65%的方差,样本按批次完美分成了两堆。当时我们以为数据废了。但仔细一看,PC2虽然只解释了8%,却把生物学表型区分开了。这说明什么?说明批次效应巨大,但生物学信号依然存在。这时候用ComBat去校正,效果通常很不错。

颜色编码:给批次贴上“标签”

颜色编码是PCA解读中非常关键的一环。说白了,就是让数据自己“说话”。

我建议在绘制PCA图时,至少准备两套着色方案:

  1. 按生物学分组着色: 用于确认生物学信号。
  2. 按批次标签着色: 用于检测批次效应。

比较这两张图,你就能直观地判断:数据的结构是由生物学驱动的,还是由技术批次驱动的。

举个例子,假设我们有一个包含三个批次的RNA-seq数据:

# 伪代码示例:生成批次标签并着色
# 假设 df 包含样本名和批次信息
batch_colors <- c("Batch1" = "#e74c3c", "Batch2" = "#3498db", "Batch3" = "#2ecc71")

# 绘制按批次着色的PCA图
plot(pca_result, col = batch_colors[df$batch], pch = 19)
legend("topright", legend = names(batch_colors), col = batch_colors, pch = 19)

在实际项目中,我习惯把PCA结果和批次信息做成一张表,这样方便后续分析:

样本ID PC1 PC2 PC3 批次 表型组
S001 -12.34 4.56 2.10 Batch1 Case
S002 -11.78 3.89 2.45 Batch1 Control
S003 15.21 -5.67 1.98 Batch2 Case
S004 14.89 -6.01 2.33 Batch2 Control
S005 0.56 12.34 -1.02 Batch3 Case
S006 -0.23 11.89 -1.45 Batch3 Control

你看这张表。S001和S002都来自Batch1,它们的PC1值都在-12附近,非常接近。而S003和S004来自Batch2,PC1值都在15附近。这初步表明,PC1这个主成分,很有可能捕获的就是批次之间的差异。

常见的坑,我曾经踩过:

  • 只看PC1和PC2: 有时批次效应藏在PC3或PC4里。我会建议至少看前5个PC。
  • 颜色瞎选: 批次标签的色差要足够大。别用两个相近的蓝色,那样你根本分不清。我个人推荐使用RColorBrewer或viridis包。
  • 忽略了生物学因素: 如果批次和生物学分组完全相关(比如,Batch1全是Case,Batch2全是Control),那PCA图上的分离到底是谁引起的?这时候你需要更复杂的分析方法。

颜色编码的实操技巧

嗯,这里有一些我在实战中总结的小窍门:

  • 透明度: 数据点重叠时,调节alpha透明度非常管用。不然一堆黑点糊在一起,啥也看不见。
  • 形状编码: 除了颜色,还可以用不同的点形状(比如圆圈、三角、方块)来编码另一个变量。比如颜色代表批次,形状代表性别,一眼能看出三重关系。
  • 图例要清晰: 图例是解读PCA图的罗盘。图例一定要标注清楚,字号别太小。
  • ellipse(椭圆): 给每个批次加一个置信椭圆,可以帮你快速判断聚类的紧凑程度和重叠情况。

我的一个小习惯:

我通常会把PCA图做成交互式的,比如用plotly包。这样我可以用鼠标悬停查看每个样本的具体批次和表型信息。在数据探索阶段,这比静态图灵活得多。

最后说一句:PCA是探索性分析工具,不是严格的统计检验。它能给你强烈的“信号”,但不能告诉你这个信号的p值是多少。别用它来做正式的假设检验,它的使命是帮你发现模式,生成假设。

当你从PCA图上看到明显的批次分离时,别慌。这恰恰说明你对自己的数据有更清晰的认识了。下一步,就是拿出ComBat来“拯救”这些数据。