# 用决策图串联错误目标、依赖条件与可用程序
fig, ax = plt.subplots(figsize=(12, 8)) # 为四层方法选择路径预留画布
# 在顶部提出需要回答的研究设计问题
ax.text(0.5, 0.95, '如何选择多重检验校正方法?', # 放置方法选择图的入口问题
# 用醒目字号区分入口与后续分支
fontsize=16, fontproperties='Source Han Serif SC', ha='center', weight='bold') # 居中强调决策起点
# 第一层:目标
ax.annotate('你的首要目标是什么?', xy=(0.5, 0.85), # 先要求明确FWER或FDR控制目标
xytext=(0.5, 0.85), fontsize=12, fontproperties='Source Han Serif SC', # 把目标问题置于两条分支上方
ha='center', va='center', # 让问题文字在节点框中居中
bbox=dict(boxstyle='round,pad=0.5', fc='lightblue', alpha=0.5)) # 用蓝色框标识共同决策节点
# 第二层分别给出两种不可互换的错误控制目标
ax.text(0.25, 0.70, '控制至少一次误拒的概率\n(FWER)', fontsize=11, fontproperties='Source Han Serif SC',
ha='center', va='center', # 将FWER定义置于左侧分支中心
bbox=dict(boxstyle='round,pad=0.5', fc='lightyellow', alpha=0.5)) # 用黄色区分家族错误率目标
# 右侧节点强调FDR是FDP的重复抽样期望
ax.text(0.75, 0.70, '控制错误发现率\n(FDR = E[FDP])', fontsize=11, fontproperties='Source Han Serif SC',
ha='center', va='center', # 将FDR定义置于右侧分支中心
bbox=dict(boxstyle='round,pad=0.5', fc='lightgreen', alpha=0.5)) # 用绿色区分错误发现率目标
# 第三层按依赖条件列出相应方法
ax.text(0.25, 0.50, '使用 FWER 控制方法:', fontsize=11, fontproperties='Source Han Serif SC',
ha='center', weight='bold') # 标明左侧候选都控制FWER
ax.text(0.25, 0.42, '• 任意依赖:Bonferroni / Holm\n• 独立或特定正依赖:Hochberg', # 区分任意依赖与附条件的FWER程序
fontsize=10, fontproperties='Source Han Serif SC', ha='center', # 保持两行条件说明居中可读
bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8)) # 用白框承载具体方法清单
# 右侧列出FDR程序及各自依赖前提
ax.text(0.75, 0.50, '使用 FDR 控制方法:', fontsize=11, fontproperties='Source Han Serif SC',
ha='center', weight='bold') # 标明右侧候选都针对错误发现率
ax.text(0.75, 0.42, '• 独立/PRDS:BH\n• 任意依赖:BY\n• Storey:需额外条件', # 区分三类FDR程序的依赖前提
fontsize=10, fontproperties='Source Han Serif SC', ha='center', # 对齐三类FDR方法的条件说明
bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8)) # 用白框承载依赖条件清单
# 第四层:应用场景
ax.text(0.25, 0.25, '典型应用:', fontsize=11, fontproperties='Source Han Serif SC', # 引出误拒代价较高的应用示例
ha='center', weight='bold') # 标出FWER方法的高误拒代价场景
ax.text(0.25, 0.15, '• 高频交易策略验证\n• 重大投资决策\n• 高风险决策', # 列出适合优先控制FWER的场景
fontsize=10, fontproperties='Source Han Serif SC', ha='center', # 让三个高风险场景保持同一视觉层级
bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8)) # 用白框限定应用示例而非普遍处方
ax.text(0.75, 0.25, '典型应用:', fontsize=11, fontproperties='Source Han Serif SC', # 引出选择FDR程序前的核对清单
ha='center', weight='bold') # 标出FDR方法使用前的必要核对
ax.text(0.75, 0.15, '前提:\n• 单项 p 值有效\n• 核对依赖条件', # 添加FDR适用前提
fontsize=10, fontproperties='Source Han Serif SC', ha='center', # 居中呈现两个不可省略的推断前提
bbox=dict(boxstyle='round,pad=0.5', fc='white', alpha=0.8)) # 用白框强调前提而非结果承诺
# 用箭头把共同目标问题分流到两类错误率
ax.annotate('', xy=(0.35, 0.70), xytext=(0.45, 0.82), # 连接入口与左侧FWER分支
arrowprops=dict(arrowstyle='->', lw=2)) # 用实线箭头表示决策方向
ax.annotate('', xy=(0.65, 0.70), xytext=(0.55, 0.82), # 连接入口与右侧FDR分支
arrowprops=dict(arrowstyle='->', lw=2)) # 保持两条分支的视觉权重一致
ax.set_xlim(0, 1) # 固定标准化横坐标以稳定节点布局
ax.set_ylim(0, 1) # 固定标准化纵坐标以稳定层级间距
ax.axis('off') # 隐藏坐标轴以突出方法选择路径
plt.tight_layout() # 自动调整子图间距
plt.show() # 输出完整方法选择路径供课堂讨论