1. 可复现分析工程导论
组学数据分析有一个很尴尬的现实:同一份原始数据,换一台机器、换一个分析人员、甚至只是隔了三个月由同一个人重跑,结果都可能对不上。可复现性(reproducibility)讨论的正是这件事——在给定原始数据、分析代码、运行环境和参数的前提下,独立的一方能否得到与原始分析在统计意义上一致的结果。它不等于“结果正确”,而是“结果可被稳定地重新得到”。这一点必须先说清楚,因为很多初学者会把可复现等同于可重复实验(repeatability),前者关注计算过程能否被独立重建,后者关注同一实验条件下测量本身的波动。
可复现性危机在组学领域并非危言耸听。2016年《Nature》对1500余名科研人员的调查显示,超过70%的人尝试重复他人实验时失败,超过50%的人甚至无法重复自己的实验。组学场景下的典型翻车案例包括:一篇转录组差异表达分析中,作者用DESeq2得到237个差异基因,但审稿人用相同代码重跑却得到189个——原因是作者在R 3.6环境下使用了默认的独立过滤策略,而审稿人用的是R 4.0后更新的默认参数;另一个常见案例是单细胞分析中,作者未固定随机种子,UMAP降维每次运行都得到不同聚类边界,导致细胞类型注释无法对齐。这些问题的根源往往不是科学假设错误,而是工程细节失控。
1. 环境漂移——软件版本、依赖库、系统库、编译器差异;
2. 隐式状态——随机种子、全局变量、工作目录、缓存文件;
3. 手工步骤——在Excel里手动改了一列、在图形界面里点了几下;
4. 数据与代码脱节——原始数据被覆盖、中间文件命名混乱、参数散落在聊天记录里。
要解决这些问题,需要把“工程化思维”引入组学分析。工程化思维的核心不是写更多代码,而是把分析过程当作一个可构建、可测试、可交付的系统来对待。具体来说,它要求我们做到四件事:第一,环境可声明——用conda、renv、Docker或Singularity把依赖版本写进配置文件,而不是靠“我记得装过”;第二,流程可编排——用Snakemake、Nextflow或WDL把分析步骤串成有向无环图,明确每一步的输入、输出和参数;第三,结果可追溯——每个输出文件都能回溯到对应的代码版本、参数和输入数据;第四,随机性可控——所有涉及随机抽样的步骤(如聚类、降维、bootstrap)必须显式设置并记录随机种子。
上图把可复现分析工程拆成五个层次:原始数据层、环境声明层、流程编排层、执行与参数控制层,以及最终的可复现输出与不可复现风险对照。右侧的虚线回路表示审计与回溯——当输出出现异常时,能够沿着这条路径反向定位到具体是哪一层的哪个参数或版本出了问题。这个框架不是理论摆设,而是后续每一章要逐层落地的施工图。
课程全景围绕这条主线展开。第一部分建立可复现性的概念基础与工程思维,包括版本控制、项目目录规范、数据完整性校验;第二部分深入环境管理,讲清楚conda与renv的锁定机制、Docker镜像的构建与分发、跨平台兼容性处理;第三部分进入流程编排,用Snakemake和Nextflow把零散脚本改造成可调度、可并行、可断点续跑的工作流;第四部分处理组学特有的可复现难题,如随机种子管理、批次效应校正的可追溯性、多组学数据整合时的标识符映射;第五部分覆盖结果交付与长期归档,包括报告自动化、容器化封装、数据与代码的联合发布。每一部分都会给出可运行的示例配置和判断标准。
需要强调的是,可复现性有程度之分。最低限度是“同一台机器上能重跑”,中等程度是“同一操作系统、同一软件大版本下能重跑”,最高程度是“任意支持容器化的平台上都能重跑”。课程的目标是帮助读者达到最高程度,但实际项目中可以根据交付要求选择合适级别。例如,内部探索性分析可能只需要固定随机种子和记录参数,而准备发表的论文分析则应当提供完整的容器镜像和版本锁定文件。
最后,可复现性工程不是一次性的清理工作,而是贯穿分析全生命周期的习惯。从项目第一天就建立规范的目录结构、从第一次运行就固定随机种子、从第一版代码就纳入版本控制,远比事后补救成本低。接下来的章节将逐一展开这些实践,每一节都会给出具体的操作对象、参数示例和判断依据,帮助读者把“可复现”从口号变成日常操作。