3. 实验设计对批次效应的影响:随机化、阻断、平衡设计的基本原则与经典案例
做RNA-seq实验设计的时候,很多人第一反应是“把样本收齐了,一次性送测序”。这个想法很危险。样本不是攒得越多越好,关键在于你怎么分配它们到不同的批次里。
我之前帮一个合作课题组排查过复现问题。他们的数据,两次重复实验的差异基因列表重叠率不到20%。一查实验记录,发现所有处理组样本都在第一批测,所有对照组样本都在第二批测。这就麻烦了——你没法区分哪些基因是真的响应处理,哪些是被批次效应“伪装”出来的。
所以,这一章我重点讲三个设计原则:随机化、阻断、平衡。掌握了它们,你就能在源头控制住批次效应。
3.1 随机化:把不可控因素打散
随机化的核心思想很简单:别让系统性的偏差有机会形成。你想想看,如果某个批次刚好碰上升温失误,而你的处理组样本全部堆在这个批次里——那这个升温的影响就和处理效应完全混在一起了。随机化就是把样本“打散”到各个批次,让这些不可控因素均匀分布。
随机化的基本原则
- 每个样本被分配到某批次、某泳道、某轮建库的概率应是均等的
- 实验条件的潜在变化(时间、操作员、试剂批号)会随着样本随机分布
- 任何批次依赖的系统误差都会转化为随机噪声,而不是混杂因子
我在实际项目里习惯用 块随机化 的方法。把样本按处理组分组,然后在每个组内做随机排序,再把排序后的样本依次分配到批次。这样既能保证均衡,又能确保随机性。
小技巧: 做随机化分配时,建议记录随机数种子。这样一旦有人质疑分配方案,你可以复现当时的随机结果,提高可信度。
3.2 阻断设计:把已知干扰来源隔离
阻断设计说白了,就是把你知道可能产生批次效应的因素显式地纳入设计。举个例子,你要在三个不同日期提取RNA——那你不如直接把“提取日期”当作一个阻断因子,每个处理组在每个日期里都抽几个样。
我记得一个经典案例:
- 不好的设计: 周一提取所有处理组RNA,周二提取所有对照组RNA
- 好的设计: 周一、周二、周三每天都提取一部分处理组和一部分对照组的RNA
阻断设计的好处很直接:当你做差异分析时,可以把“日期”引入线性模型作为协变量,这样就能去除掉跨日期波动带来的批次效应。
注意: 阻断因子一旦确定,就不要中途更改。如果你一开始把“提取日期”设为阻断因子,结果中途换了操作员,测序也不再连续——那这个阻断就失效了。我曾在一个项目中看到有人把“测序批次”当成阻断,结果样本被拆到两轮测序,且两轮用的试剂批次完全不同——这本质上已经不再是同一个阻断因素了。
3.3 平衡设计:保证每个处理组的样本量在各批次中均匀
平衡设计,是对随机化和阻断设计的补充。它要求每个处理组在每个阻断水平上的样本数量保持相似。为什么重要?因为你一旦不平衡,某些处理组在某批次的比例偏高,那批次差异就可能和组间差异纠缠起来。
看看这张对比表,你就明白了:
| 设计类型 | 说明 | 对批次效应影响 |
|---|---|---|
| 完全随机设计 | 所有样本随机分配到批次 | 若样本量小,容易失衡 |
| 随机区组设计 | 每个区组(如日期)内各处理组样本量一致 | 可有效阻断已知批次源 |
| 平衡不完全区组设计 | 区组内无法容纳所有处理组时,保证每个处理对出现的次数平衡 | 适用于大规模实验 |
我个人的经验是:在多数RNA-seq项目中,随机区组设计是最实用的。它能用最少的样本量实现对已知批次效应的控制。但要注意,在实际操作中,不能只平衡“样本”,而忽视了试剂、操作员、文库制备等环节的均匀性——那才是批次效应真正的温床。
避坑: 我曾经在一个协作项目中看到,设计时样本身份在各批次间是均衡的,但所有高表达基因的文库全部在一个批次建库——因为它们是按“表达量由高到低”排序后取前一半。结果后续分析中,这批基因在差异表达中被反复检出,其实是建库效率差异导致的假阳性。这就是典型的“隐性不平衡”。
3.4 一个经典案例:大鼠肝脏RNA-seq实验设计
假设你要做一个大鼠肝脏的RNA-seq,比较药物处理组和对照组,每组8个样本。你可以在0天、3天、7天分别取样。那实验设计可以这样:
- 随机化: 每个取样日的8个样本(处理+对照各4只)随机分配到不同提取批次
- 阻断: 把“取样日”作为阻断因子,在分析模型中把它当作协变量
- 平衡: 每个取样日,处理组和对照组各4个样本,均匀分布在提取批次中
这样,即使不同取样日的样本在提取、建库、测序环节存在偏差,它们也被“阻断”掉了——你最终比较的仍然是处理组 vs 对照组的差异。
3.5 设计阶段的一个SVG框架图
下面这张图展示了我常用的实验设计矩阵结构:横轴是样本分组(处理/对照),纵轴是阻断因子(提取日期/测序批次),色块表示每个样本所在的批次,箭头说明批次效应的隔离关系。
从图里你看出了什么? 每个阻断因子(提取日期、文库批次、测序批次)下,处理组和对照组都有对应的样本批次。这不是巧合,是设计的结果。换句话说,无论你从纵轴哪个维度切一刀,都能找到两个处理组的样本在同一个批次里——这就保证了比较时批次因子不成为混杂变量。
3.6 实操建议:用R代码生成平衡设计表
你不太可能手动画矩阵。我一般用R的 blockrand 包来生成随机化清单。下面是我常用的脚本片段:
library(blockrand)
# 设置随机数种子,保证可复现
set.seed(2024)
# 生成随机block分配
blocks <- blockrand(
n = 16, # 总样本数
num.levels = 2, # 2个处理组
levels = c("Treat", "Control"),
block.sizes = 4 # 每个block内各处理组样本平衡
)
# 分配批次:block内随机排序后依次分配
blocks$BatchID <- rep(1:4, each = 4)
# 查看分配结果
print(blocks[, c("id", "treatment", "BatchID")], row.names = FALSE)
这个脚本会生成一个包含样本ID、处理组、批次号的表格。每个batch里处理组和对照组各2只,非常均衡。我习惯把这个表格直接贴在实验记录里,作为设计文档的一部分。
你想想看,有了这个步骤,后续任何人对批次分配有疑问,都可以回看这份索引——透明、可审计、可复现。
3.7 总结
实验设计对批次效应的控制,说白了就是三个字:分、隔、匀。
- “分”:把样本随机分配到各批次,避免系统性偏差
- “隔”:用阻断设计隔离已知的批次来源
- “匀”:保持各处理组在各阻断水平上的样本量均匀
做到这三条,批次效应就从“无法控制的随机因素”变成了“可在模型中显式处理的设计变量”。我个人习惯在提交测序之前,先让合作方看一眼实验设计表格——90%的问题其实都可以在测序之前发现并修正。测序一旦开始,就晚了。