从血压计到CT扫描:手把手教你用Python复现Bland-Altman一致性分析(附完整代码)

张开发
2026/4/6 19:28:45 15 分钟阅读

分享文章

从血压计到CT扫描:手把手教你用Python复现Bland-Altman一致性分析(附完整代码)
从血压计到CT扫描用Python实战Bland-Altman一致性分析在医疗数据分析和医疗器械验证领域我们经常需要评估两种测量方法的一致性——无论是比较新旧款血糖仪的准确性还是验证AI算法与放射科医生在CT扫描测量中的差异。Bland-Altman分析正是解决这类问题的金标准。但传统教程往往停留在理论层面本文将带您用Python完整实现自动化生成带置信区间的Bland-Altman图执行正态性检验Shapiro-Wilk处理非正态数据的百分位数法替代方案可直接套用的代码模板与临床报告解读技巧1. 环境准备与数据加载1.1 安装必要库确保已安装以下Python库可通过pip安装pip install pandas scipy statsmodels matplotlib seaborn1.2 构建示例数据集我们模拟两组血压测量数据单位mmHg分别来自传统水银血压计Method_A和电子血压计Method_Bimport pandas as pd import numpy as np data { Method_A: [120,125,130,135,140,145,150,155,160,165,170,175,180,185,190], Method_B: [118,124,131,136,140,145,150,154,162,168,176,182,186,188,193] } df pd.DataFrame(data)提示实际应用中建议至少收集30组配对数据以满足统计要求2. 核心计算与可视化2.1 差异计算与基本统计量df[Difference] df[Method_A] - df[Method_B] df[Average] (df[Method_A] df[Method_B])/2 mean_diff df[Difference].mean() std_diff df[Difference].std() loa_upper mean_diff 1.96*std_diff loa_lower mean_diff - 1.96*std_diff2.2 带置信区间的Bland-Altman图使用statsmodels实现带95%CI的LOAimport matplotlib.pyplot as plt import statsmodels.api as sm # 计算LOA置信区间 ci 1.96 * std_diff * np.sqrt(3/len(df)) plt.figure(figsize(10,6)) plt.scatter(df[Average], df[Difference], alpha0.7) plt.axhline(mean_diff, colorred, linestyle--) plt.axhline(loa_upper, colorgreen, linestyle:) plt.axhline(loa_lower, colorgreen, linestyle:) plt.fill_between([df[Average].min(), df[Average].max()], [mean_diff-ci, mean_diff-ci], [mean_diffci, mean_diffci], colorred, alpha0.1) plt.title(Bland-Altman Plot with 95% CI) plt.xlabel(Average of Two Methods (mmHg)) plt.ylabel(Difference (A-B)) plt.show()3. 进阶验证与异常处理3.1 正态性检验使用Shapiro-Wilk检验验证差异值的正态分布假设from scipy.stats import shapiro stat, p shapiro(df[Difference]) print(fShapiro-Wilk p-value: {p:.4f}) if p 0.05: print(差异值符合正态分布) else: print(警告差异值不符合正态分布)3.2 非正态数据的替代方案当数据不满足正态性时可采用百分位数法lower_perc np.percentile(df[Difference], 2.5) upper_perc np.percentile(df[Difference], 97.5) print(f百分位数法LOA: [{lower_perc:.2f}, {upper_perc:.2f}])4. 报告生成与临床解读4.1 自动化报告模板生成包含关键指标的DataFramereport pd.DataFrame({ Metric: [Mean Difference, SD of Differences, Upper LOA, Lower LOA, LOA CI Width], Value: [mean_diff, std_diff, loa_upper, loa_lower, 2*ci], Unit: [mmHg, mmHg, mmHg, mmHg, mmHg] }) print(report)4.2 临床意义解读要点系统偏差平均差异(mean_diff)反映两种方法的系统性差异可接受范围LOA范围应小于临床允许误差如血压测量通常接受±15mmHg趋势分析散点图形态揭示测量误差是否随数值增大而变化5. 扩展应用医学影像分析案例将方法应用于CT扫描测量的一致性评估# 模拟AI算法与放射科医生的测量数据 ct_data pd.DataFrame({ Radiologist: [45.2, 38.7, 52.1, 48.9, 41.3], AI_Algorithm: [43.8, 39.1, 50.9, 49.2, 42.0] }) # 复用前面的分析流程 ct_data[Difference] ct_data[Radiologist] - ct_data[AI_Algorithm] mean_diff_ct ct_data[Difference].mean() print(fCT测量平均差异{mean_diff_ct:.2f}mm)实际项目中我发现当处理医学影像数据时Bland-Altman分析特别适合评估AI算法与人工标注的一致性。曾有个肺部结节测量的案例通过这种方法发现AI在大于3cm的结节中存在系统性低估这个发现直接改进了后续的算法训练策略。

更多文章