置换检验与批次校正校验的结合思路

批次校正搞完,不是拍个手就完事的。你得确认校正有没有“矫枉过正”,或者压根没校到位。我习惯的做法是——把置换检验请过来,给校正结果做个严格体检。

为什么非要用置换检验?

批次校正方法(比如 ComBat、limma)本身是参数模型,会假设数据符合某种分布。但实际数据往往不听话——异质性、离群点、批次效应非对称,这些都会让模型假设崩掉。你直接看箱线图、PCA 觉得“好像好了”,但统计上到底过没过?说不准。

置换检验的好处是不依赖分布假设。我有个项目,校正后 PCA 看起来混在一起了,但真实生物差异也被抹掉了一部分。幸亏当时做了置换检验,发现统计量显著偏离零分布,赶紧调了校正参数。嗯,从那以后我再也不敢只看图了。

核心思路:把“校准后的批次效应”变成可检验的假设

说白了,我们想回答一个问题:

校正之后,样本的批次标签对表达值的影响,还显著吗?

如果校正彻底,批次标签应该没有解释力——也就是说,用批次标签做分组变量,组间差异应该接近随机。置换检验刚好能模拟这个随机过程:把批次标签打乱,看真实分组下的统计量处于打乱后分布中的什么位置。

结合思路三要素:

  1. 设计一个合适的统计量,比如批次间方差比、批次内相关差异、分类器对批次标签的预测准确率。
  2. 构建零分布:反复打乱批次标签,重新计算统计量。
  3. 比较与决策:真实统计量落在零分布两端,就说明校正没搞干净;落在中间,说明批次效应已被消除。

我常用的三种统计量设计方法

统计量选得不好,置换检验等于白做。分享一下我在几个真实数据集里的经验。

统计量含义适用场景
F 统计量(批次间方差比)校正后各批次间的方差 / 批次内方差多批次、期望批次间方差一致的场景
批次标签分类准确率用校正后表达值训练一个简单分类器(比如kNN),预测批次标签的正确率批次差异复杂、非线性的情况
批次间相关系数差异校正后样本两两之间的相关系数,按批次内外分组求差异需要保留样本间相似结构时

技巧:我一般会同时用两三种统计量,取共识结果。单一统计量容易被特殊结构骗过去。

置换检验流程(结合批次校正校验)

每次做这个流程,我都写一个简单的管道脚本,下面是个伪代码风格的步骤。

1. 输入:校正后表达矩阵,样本批次标签
2. 计算真实统计量 T_real
   - 比如:按批次分组,计算批次间方差 / 批次内方差 → F值
3. 设定置换次数 N(建议 ≥ 1000)
4. 循环 i in 1:N:
   a. 打乱批次标签(随机重排)
   b. 用打乱后的标签重新计算统计量 T_perm[i]
5. 统计 T_perm 中 ≥ T_real 的比例 → 得到 p 值
6. 决策:若 p < 0.05,说明批次效应仍显著 → 校正不足

你看,逻辑上很简单。但真正跑起来有几个坑,我挨个说。

避坑指南

曾经有一次,我把置换次数设成 100,结果 p 值死活算不准。 后来发现,小样本+少置换,零分布根本构建不光滑。建议最少 1000 次,如果数据量小(比如每组 5 个样本),要跑到 5000 甚至 10000。

  • 注意标签结构:如果批次内还有生物分组,打乱时不能破坏配对关系。我习惯用“区块置换”或“保持分组内置换”。
  • 多重检验:如果你同时检验好几万基因的校正效果,那就需要对 p 值做 FDR 矫正。我个人习惯用 Benjamini-Hochberg。
  • 计算耗时:几十个样本、几万个基因,1000 次置换 × 计算统计量,还是挺吃内存的。我一般先随机抽几千个基因做快速探查,确认趋势后再全量跑。

流程图:整个结合思路一目了然

下面这张 SVG 把从原始数据到决策的全流程串起来了,方便你贴在项目报告里用。

置换检验与批次校正校验结合流程 原始表达数据 批次校正(ComBat等) 校正后表达矩阵 选择统计量(F值/准确率等) 真实批次标签 → Treal N次随机置换 → Tperm 分布 比较 → p 值

个人习惯:我画完这个流程后,会直接对着它写代码,一个函数一个函数拆。先写统计量计算函数,再写置换循环,最后写决策逻辑。这样调试起来快很多。

实操要点总结

  • 不要只依赖一个统计量。 至少用两个,比如 F 值 + 分类准确率,交叉验证结论。
  • 置换次数要够。 我通常设 2000 次,如果 p 值在 0.04~0.06 浮动,就加到 5000 次再确认。
  • 小心样本量太小。 单批次只有 3~5 个样本时,置换检验的分辨率有限。这时我配合留一法交叉验证一起看。
  • 结果解读要有底线。 p < 0.05 说明批次效应还没消干净,但不是说你之前的校正没用——可能只是需要更强调参数,比如增加 ComBat 的“稳健估计”选项。

好了,这些思路足够你上手做自己的校验流程了。下回我会带大家完整走一遍 Python 代码实现,包括怎么选统计量、怎么处理多重检验、怎么画结果图。咱们到那一步的时候,我会把上面这些思路一字一句转成可运行的代码。