代谢组学的可信度危机不是抽象批评,而是可以被拆解的四笔具体债务:鉴定瓶颈、流程异质性、报告不完整、验证缺失。每笔债务都有正在推进的偿还方案,但都没还清。
非靶向数据大部分特征永远停在"未知"。这不是仪器灵敏度问题而是组合爆炸问题:化学空间里可能的代谢物数量远超任何谱库。后果是文献里大量"identified"其实只是第 2、3 级注释(5.2 节),跨研究比较时同名异物的风险始终存在。偿还方案:标准品库扩容、CCS 库、计算谱预测——都在推进,都赶不上化学空间的膨胀速度。
同样叫"血浆非靶向",不同实验室的取样、提取、色谱、数据处理参数各不相同。就算都正确,拼在一起也比较不了。偿还方案:参考物质。NIST 释放的血浆标准参考物质(SRM 1950)被各实验室当作公共锚点——你的方法测它得到什么,别人就知道怎么换算。方法学报告规范(如 MSI 最小报告标准)要求把参数全写出来,期刊审稿逐步在执行。
翻转的 iceberg:论文只报了顶端的显著结果,QC 数据、剔除样品、调过的参数都沉在水下。别人拿着同样数据换个参数就能得到不同结论——社区复现研究发现,同一原始数据不同分析团队的处理选择(峰检测参数、填补方法、归一化)能造成结果差异大到结论翻转。
偿还方案的核心一句话:原始数据与分析代码必须随文公开(MetaboLights、Metabolomics Workbench 两个公共库承担存证)。这不是道德呼吁,是让复现成为可能的最低条件。
6.1 节已详述:发现队列 AUC 冒充临床性能、缺乏独立队列复核。加上期刊对"阳性结果"的偏好,领域里堆积了大量未经复核的候选标志物。系统调研显示,进入临床指南的代谢组学标志物数量与文献产出量严重不成比例——这就是债务的利息。
💡 关键直觉:这四笔债务在"越小的实验室越难偿还"的意义上是系统性的。个人能做的最有效动作是管好自己的两件小事——QC 数据全公开、分析代码可复跑。信任是靠这两件小事攒出来的。
第 8 章把对策整理成可执行的工具链与规范清单。
注释覆盖率:非靶向数据中能 Level 2 以上注释的通常不足三成,环境样本更低于 10%——"检测到了但不知道是什么"是常态。定量线性:单次分析跨 7–9 个数量级浓度,任何标曲都只覆盖局部,超线性区的报告值是伪精确。批次效应:多中心研究中批次方差常超过疾病组间方差,Harmonization 前 PCA 按中心而非按疾病分组。标准缺失:样品前处理方法学全球实验室间差异大,同一冻干血清往返测量的室间 CV 可到 30–50%。
import random random.seed(5) # 模拟 2 中心 × 2 组 × 10 样本的某代谢物浓度 data = [] for center, c_off in [("A", 100), ("B", 135)]: # 中心间系统差 35% for group, g_eff in [("对照", 0), ("病例", 12)]: for _ in range(10): data.append((center, group, c_off + g_eff + random.gauss(0, 5))) import statistics as st grand = st.mean([v for _, _, v in data]) ss_center = sum(10*(st.mean([v for c,_,v in data if c==c0])-grand)**2 for c0 in ["A","B"]) ss_group = sum(20*(st.mean([v for _,g,v in data if g==g0])-grand)**2 for g0 in ["对照","病例"]) print(f"中心间离差平方和 = {ss_center:.0f},组间 = {ss_group:.0f}") print(f"批次效应是生物效应的 {ss_center/ss_group:.1f} 倍 → 未校正前不可比较") # 校正路径:ComBat / 批内中心化,且必须保证每批内组平衡
代码揭示的比值(批次方差数倍于生物方差)是多中心代谢组学的典型处境,也是各家整合计划(如队列 harmonization 项目)的核心工程量。挑战清单的共同底色是:代谢组学的瓶颈已经从"测得出来"转到"说得清楚、测得一致"——下一阶段的竞争是标准化与数据基建,而非更高分辨的仪器。
# 12 个实验室测同一质控血清的肌酐值(uM,模拟室间试验) labs = [78, 82, 85, 91, 76, 240, 88, 83, 90, 87, 80, 86] import statistics as st med = st.median(labs) outliers = [x for x in labs if abs(x - med) / med > 0.25] clean = [x for x in labs if abs(x - med) / med <= 0.25] cv_raw = st.stdev(labs) / st.mean(labs) * 100 cv_clean = st.stdev(clean) / st.mean(clean) * 100 print(f"原始 CV {cv_raw:.0f}% → 剔除离群({outliers})后 {cv_clean:.0f}%") # 一个校准失误的实验室就能把室间 CV 推高过 30%:标准化先抓离群再谈平均