实验设计、统计推断与生物信息 本节摘要:掌握对照、随机、盲法三原则各自阻断的偏倚,正确理解 P 值与检验效能,亲手完成样本量估算与多重比较校正,认识生物信息如何把组学数据变成可检验的结论。 前五章的知识里藏着大量「研究表明」,本站回答一个元问题:研究表明的「表明」,凭什么成立?答案是一套裁决装置:设计堵住系统性偏差,统计管住随机波动,生物信息驯服数据规模。三者缺一,「表明」就只是「声称」。 一、设计三原则:各自阻断一种偏倚 对照阻断时间与环境的自变:不给对照组,「治疗后好转」就无法与「本来就会好」区分(很多疾病自愈或波动)。随机阻断选择偏倚:分组的系统性差异(把轻症分进治疗组)会在数据里伪装成疗效,随机分配让已知与未知的混杂因素在组间趋于均衡。
本节摘要:掌握对照、随机、盲法三原则各自阻断的偏倚,正确理解 P 值与检验效能,亲手完成样本量估算与多重比较校正,认识生物信息如何把组学数据变成可检验的结论。
前五章的知识里藏着大量「研究表明」,本站回答一个元问题:研究表明的「表明」,凭什么成立?答案是一套裁决装置:设计堵住系统性偏差,统计管住随机波动,生物信息驯服数据规模。三者缺一,「表明」就只是「声称」。
对照阻断时间与环境的自变:不给对照组,「治疗后好转」就无法与「本来就会好」区分(很多疾病自愈或波动)。随机阻断选择偏倚:分组的系统性差异(把轻症分进治疗组)会在数据里伪装成疗效,随机分配让已知与未知的混杂因素在组间趋于均衡。盲法阻断测量与心理偏倚:知道分组的人(医生与患者)会在观察、报告甚至处置上无意识地倾斜,双盲让这种倾斜失去着力点。三原则对应三种具体的失效模式,读文献时可以按图索骥:没有对照找「自愈误判」,随机失败找「基线不齐」,未盲找「结局评定被污染」。真实世界研究里三原则常难齐备(伦理或可行性限制),此时要做的不是假装原则还在,而是明确说出哪种偏倚无法排除、估计它把结论往哪个方向推。
P 值的正式定义窄得惊人:假设无效假说为真,观察到当前或更极端数据的概率。它不是效应大小,不是结论成立概率,更不是「偶然发生的概率」。三类高频误读逐一对照:「P 值小所以差异大」——错,P 值受样本量驱动,足够大的样本能把微不足道的差异算出极小的 P 值(统计显著不等于临床意义,大样本研究里两者常分道扬镳);「P 值大所以两组相同」——错,P 值大只说明「没检出差异」,可能是差异真不存在,也可能只是没检出(检验效能不足),「无显著差异」不能写成「无差异」;「P 等于零点零四九与零点零五一有本质区别」——错,阈值两侧是同一连续量度的人为切分,零点零六的结果配上扎实的效应量与置信区间,远比零点零四九加一个空洞的「显著」更有价值。置信区间是 P 值的好搭档:它同时给出效应大小的估计与不确定性的范围,比单独一个 P 值信息量大得多。
实验要做几次,不该拍脑袋。样本量的演算取决于四个量:预期效应大小、数据的变异性、容许的错误率(第一类错误 α,通常设零点零五)与检验效能(一减第二类错误 β,通常设零点八)。第四章的伦理站埋了样本量的伏笔,这里把公式正式展开:
import math def n_per_group_proportion(p1, p2, alpha=0.05, power=0.80): """两组率的比较: 每组样本量(正态近似)""" z_a, z_b = 1.960, 0.842 p_bar = (p1 + p2) / 2 num = (z_a * math.sqrt(2 * p_bar * (1 - p_bar)) + z_b * math.sqrt(p1 * (1 - p1) + p2 * (1 - p2))) ** 2 return math.ceil(num / (p1 - p2) ** 2) def n_per_group_continuous(delta, sd, alpha=0.05, power=0.80): """两组均数比较: 每组样本量 n ≈ 16 * (sd/delta)^2 (alpha=0.05, power=0.80)""" return math.ceil(16 * (sd / delta) ** 2) # 例一: 对照组缓解率 30%, 预期新方案提到 50% print(f"率比较: 30% vs 50%, 每组需 {n_per_group_proportion(0.30, 0.50)} 例") # 例二: 效应减半, 样本量翻四倍 print(f"率比较: 30% vs 40%, 每组需 {n_per_group_proportion(0.30, 0.40)} 例") # 例三: 连续终点, 效应量(均差/标准差)与样本量 for es in [0.8, 0.5, 0.3]: print(f"均数比较 效应量 {es}: 每组约 {n_per_group_continuous(es, 1.0)} 例") print("\n规律: 样本量与效应量的平方成反比 —— 检测的效应越小, 代价平方级上涨") print("=> 这就是为什么「阴性结果」要先问效能: 效能不足的阴性, 等于没做")
演算读出三件事:效应越小需要的样本越多(平方级);效能不足的阴性结果是无效实验(白花经费白牺牲实验动物——第一章三原则的「减少」正是靠这个公式成立);预期效应的估计要来自预实验或文献,拍脑袋的效应假设是样本量演算最常见的崩塌点。

对同一数据做很多次检验,「总有巧合显著」的概率随次数暴涨(独立检验二十次,至少一次假阳性的概率约六成四)。传统实验一次比一个终点,问题不大;组学一次测上万个分子,不校正等于从噪声里批量捞「显著」。两种校正思路各有岗位:族错误率控制(如邦费罗尼:阈值除以检验次数)把「任何假阳性都不许有」执行到底,代价是极保守——适合确认型分析;假发现率控制(如本雅明尼-霍奇伯格法)允许少量假阳性但限制其比例——适合发现型分析(筛出候选再验证)。算一遍 BH 法的直觉账:
# Benjamini-Hochberg 假发现率校正的直觉演示 p_values = [0.001, 0.004, 0.008, 0.020, 0.047, 0.210, 0.480, 0.900] n = len(p_values) fdr_target = 0.05 print(f"共 {n} 次检验, 目标假发现率 {fdr_target:.0%}\n") sorted_p = sorted(p_values) k_max = 0 for k, p in enumerate(sorted_p, start=1): threshold = fdr_target * k / n flag = p <= threshold if flag: k_max = k print(f"第 {k} 小的 P={p:<7} 阈值 {threshold:.4f} {'入选' if flag else ''}") print(f"\n结论: 前 {k_max} 个按 BH 口径入选, 预期其中假阳性不超过 {fdr_target:.0%}") print("对比 Bonferroni: 0.05/8 = 0.00625 -> 只有最小那个入选, 更保守")
跑一遍就能体会两种口径的取舍:邦费罗尼几乎把发现清零,BH 留下几个候选但给它们贴上「预期五分之一可能是假」的标签——发现型研究与确认型研究的分工,就在这两种口径之间。