实验设计:队列研究中的批次划分,QC样本插入策略,随机化与平衡

各位同学,这一章咱们来啃实验设计这块硬骨头。说实话,很多质谱数据翻车,根源都不在仪器,也不在软件——而是在上机前实验设计就埋了雷。

我个人习惯是:拿到样本清单后,先别急着做任何操作,坐下来花半小时把批次和QC计划排好。这个时间花得值,它能帮你省掉后面几周的debug环节。嗯,咱们直接进正题。

批次划分:自然批次 vs 人为批次

先搞清楚一个核心概念:批次是什么?

在DIA-NN / Spectronaut的语境下,批次是一次连续采集的数据块。你开了仪器,跑了一组样本,中间没有关机或重大维护,这就是一个批次。

但现实中没有那么完美的实验。我遇到过一个大队列项目,430个血浆样本,光采集就用了11天。中间换色谱柱、校准仪器、重启质谱……这些都是天然批次分界点。

批次类型 定义 处理策略
自然批次 仪器运行中断(关机、换柱、大修)产生的分界 必须作为批次分层变量纳入模型
人为批次 连续运行中人为划分的Block(如每24h一批) 建议也保留,用于质控对比

为什么要分这么细?说白了,不同批次的定量偏差常常超过10%。你不把它控制住,后续差异分析的假阳性就控制不住。

核心原则:每批样本总数不建议超过96个(一块96孔板),最长连续采集时间不超过72h。

我曾经接手过一个项目,用户把240个样本一次性上机跑了5天。结果前两天的数据和后三天的数据之间出现了明显的质量漂移。我检查后发现,第三天夜里色谱柱压力变化,已经灌入了系统偏差。最后这240个样本被迫当成两个批次分别归一化,用户非常痛苦。

QC样本插入策略

QC样本怎么插?我见过最典型的错误就是:QC只放在批次头和批次尾。这样做完全看不到batch内部的漂移。

正确的做法是:

  1. 批头QCx3:先跑3针QC样本,让系统稳定并建立基线
  2. 定期QC:每10-12个研究样本后插入1针QC
  3. 批尾QCx1:批次结束前再跑1针QC

你想想看,为啥要这么安排?

  • 批头QC用于评估系统初始状态,3次重复可以估算峰面积CV
  • 定期QC能捕捉采集过程中的漂移,比如保留时间偏移、强度衰减
  • 批尾QC确认结束时的状态,与批头对比能算出整批漂移量
小技巧:QC样本尽量用混合样本(pooled sample),而不是商业标准品。因为混合样本的基质和你研究样本一致,更能反映真实体系。

我建议在Spectronaut的项目配置中,直接把QC样本的Condition全部设为"QC"。这样后续的批处理文件中,筛选QC就非常方便。

# Spectronaut实验设计文件列表示例(Sample表)
FileName    Condition    Batch    RunOrder
QC_01.d     QC           1        1
QC_02.d     QC           1        2
QC_03.d     QC           1        3
S001.d      Disease      1        4
S002.d      Control      1        5
...
S010.d      Disease      1        14
QC_04.d     QC           1        15
S011.d      Control      1        16
...
QC_10.d     QC           1        25
S020.d      Control      1        26
QC_11.d     QC           1        27

随机化与平衡

这个环节最容易被忽视。我做课程前特意回想了一下,至少有三个项目因为随机化没做好,后期花了大量时间做追加归一化。

随机化指的是样本的上机运行顺序应该随机分配,而不是按照分组的顺序跑。你想想看,如果你把所有“疾病组”样本集中在一个时间段采集,万一那段时间仪器状态有波动,岂不就成了组间偏差?

平衡则是指各组的临床特征(如年龄、性别、BMI)在每个批次内分布均衡。不能把所有老年病例都塞在最后一批。

策略 目标 常见陷阱
全随机 消除时序干扰 样本数量太少时可能不均衡
区组随机 每N个样本内各组比例固定 区组大小选择不当
分层平衡 临床特征在批次间均衡 分层因子过多导致组合爆炸
警告:不要完全依赖Excel的RAND()函数做随机化。同一文件每次打开都会重新计算,生成不同的随机序列。务必使用固定的随机种子(如Python的random.seed(42))。

我给你们一个我常用的Python脚本片段:

import pandas as pd
import numpy as np

# 设定随机种子
np.random.seed(42)

# 读取样本表
samples = pd.read_csv('sample_list.csv')

# 按分组和临床特征分层随机排列
samples['rand_order'] = np.random.rand(len(samples))
samples.sort_values(['Batch', 'rand_order'], inplace=True)

# 重新编号运行顺序
samples['RunOrder'] = range(1, len(samples) + 1)

# 输出
samples.to_csv('run_order_balanced.csv', index=False)

这里的关键是:加了Batch作为分层变量。先按批次分堆,再在每批次内部随机。这样就既保证了随机化,又让批次结构保持不变。

实战案例:一个200样本队列的批次规划

我们用一个案例把上面所有点串起来。

背景:200例血清样本,两组各100例(疾病/对照)。临床特征包括年龄和性别,需要纳入平衡设计。仪器可用时间72h,单针时间为45min。

计算约束:

  • 每批次最大样本量 = 72h × 60min ÷ 45min = 96针
  • 考虑QC ~ 每批96针中QC占 ≈ 10-12针(批头3+每10个研究样本1+批尾1)
  • 研究样本 = 96 - 12 = 84针/批
  • 200个样本 ÷ 84 ≈ 2.38 → 分3批

批次规划:

Batch 1: 68 研究样本 + 12 QC = 80 针
Batch 2: 66 研究样本 + 12 QC = 78 针
Batch 3: 66 研究样本 + 12 QC = 78 针
Total:  200 研究样本 + 36 QC = 236 针

平衡检查:确保每批疾病/对照 ≈ 33-34例,年龄和性别分布无显著差异。

失败经验:我曾经有一次没有做批次间的年龄平衡。结果第2批的平均年龄比第1批大了8岁。后期差异分析发现的好几百个“显著蛋白”,其实是年龄相关蛋白的批次混淆。教训非常深刻。

下面这张图把三个核心策略的关系展示得很清楚:

队列研究批次质控核心策略 批次划分 自然批次 / 人为批次 QC插入策略 批头3 / 每10针1 / 批尾1 随机化与平衡 区组随机 / 分层平衡 低偏差的DIA定量数据 批次效应可控 / 组间比较可靠 ⚠️ 三条腿缺一不可 批次划分不对 → 无法控制系统偏差 QC插入不够 → 无法监测漂移 / 随机化失衡 → 引入混淆
我的建议:你可以在正式上机前用这个框架画一下流程图。先把批次标出来,然后逐个插入QC位点,最后检查随机化和平衡性是否达标。这个过程用不了30分钟,但价值巨大。

好了,这一章的核心内容就是这些。实验设计的质量直接决定了后续数据分析的可靠程度。记住:不要怕在实验设计上花时间,这部分投入的回报率是最高的。