行业资讯
📅 2026/9/2 2:34:37
基于GBD数据库与BAPC模型的疾病负担预测:R包实操指南
简介面向GBD数据库分析人员的R语言资源包聚焦贝叶斯年龄-时期-队列BAPC分析适合研究疾病负担、肿瘤发病/死亡趋势及预测的流行病学工作者也适合想深入理解BAPC建模流程的R中级用户。资源共41个文件以r代码、rd帮助文档、rda示例数据、txt数据文件和rmd分析脚本为主还包括R包元数据、命名空间及构建忽略文件压缩包仅约57KB结构清晰。内容以Nordpred包为核心涵盖R函数源代码、估计与预测对象的方法、挪威癌症示例数据及数据预处理流程便于读者复现预测模型并迁移到自己的GBD数据上。已有2083人学习下载适合作为BAPC分析入门和R包二次开发的参考工具。 GBD数据库里的疾病负担数据做公共卫生和临床科研的朋友应该都不陌生。每年更新一次覆盖全球和各地区不同年龄、性别、死因的发病、死亡、DALY数据又全又方便下载是疾病负担研究的标配数据源。但拿到数据后的下一步往往不是画几张趋势图就结束而是被追问“未来五年、十年的负担会怎么走”。这时候就需要把BAPC分析搬出来。BAPC全称Bayesian Age-Period-Cohort也就是贝叶斯年龄-时期-队列模型它能把疾病负担的历年变化拆成年龄、时期、出生队列三个维度并在这个框架下外推未来。R生态里已经有一套成熟工具链来完成这件事核心是BAPC包加INLA包再配上数据处理、可视化的几个辅助包。这篇文章主要分享我实际使用中一直在用的R包组合、从GBD数据到预测图的完整流程以及一些常规教程里不会写明的坑适合已经会基础R操作、想进一步做疾病负担预测的朋友参考。1. GBD数据库与BAPC分析的基本盘1.1 GBD数据库能给你的正好是BAPC需要的输入GBD数据库来自IHME数据字段基本都是标准化的。做BAPC预测本质上需要两类统计量一个是各年份、各年龄段的疾病事件数比如死亡数、患病数或发病数另一个是同样维度的暴露人口数。这两个变量在GBD数据库里都能拿到。GBD结果表里如果你选MeasureDeaths、MetricNumber导出的val就是事件数如果你同时选MetricRate可以按率换算人口或者直接去下载人口估计。从操作角度我一般建议在GBD Results Tool里把事件数和人口数据一起准备好省得后面再去对齐年份和年龄组。需要注意GBD的年龄变量有多种层级做APC最好选统一的5岁年龄组比如0-4、5-9一直到95这样每个分组都有中点后面计算队列效应时方便很多。1.2 为什么疾病负担预测要选APC模型传统做法比如直接对时间做线性回归问题在于忽略了一个事实人群中的年龄结构是不断变化的同样一个总死亡率老化的社会和新生的社会含义完全不同。APC模型把观察到的率分解成三个部分年龄效应对应人体最自然的生理风险变化时期效应对应某一年所有年龄段都会受到的环境、医疗、政策等共同影响队列效应对应不同出生年份的人特有的暴露历史。举个简单例子中年人的肺癌风险可能同时受年龄、时期和队列影响年龄越大本身风险就高这些年诊断手段变化又导致检出的时期效应不同年代出生的人吸烟行为不同又构成队列效应。三个效应叠在一起才能相对合理地解释历史走势也让外推预测有更扎实的结构基础。可以说APC是目前疾病负担预测最常用的框架之一。1.3 BAPC方法为什么能又快又好地做到这一点APC模型在数学上有个老问题年龄等于时期减队列三个变量存在线性关系直接放进传统回归里会出现完全共线性无法唯一求解。贝叶斯方法不回避这个识别问题而是通过指定先验分布来约束效应曲线。BAPC包的实现核心是用随机游走先验对年龄、时期、队列效应做平滑然后借助INLA做近似贝叶斯推断。之所以强调INLA是因为它比传统MCMC快得多。比如你用rjags跑一个十几二十个年龄组、几十年的APC模型光收敛判断就够头疼INLA用积分嵌套拉普拉斯逼近几秒到几分钟出结果对GBD这种大样本场景极友好。BAPC包本质上就是把这套建模流程封装成了更友好的接口你不一定要自己写INLA公式。如果你有特殊需求也可以绕过BAPC包直接用INLA手写随机游走模型但日常摸数据BAPC的开箱体验最好。2. R包清单从数据处理到预测出图2.1 核心包BAPC和INLA缺一不可核心就是前面说的两个。BAPC包负责组织APC数据结构、调用建模函数、输出后验预测结果INLA是BAPC运行的底层算力也是贝叶斯推断真正发生的引擎。要注意INLA并不在CRAN上装法特殊后面实操里我会再演示。用BAPC时不需要直接操作INLA对象但如果你需要诊断模型、调整先验还是得学一点INLA的语法。另外BAPC包的更新频率不算特别高如果你装了新版R有可能会遇到兼容性问题我后面会专门写一段排查记录。2.2 辅助包数据读取、清洗、可视化围绕核心包数据处理阶段我用得最多的是下面这几个。它们不是BAPC分析的必须项但没有它们数据整理阶段会非常痛苦。GBD的真实变量名比较长又带着upper、lower等列用dplyr的filter和select可以快速缩小处理范围。类型包名主要用途核心分析BAPC贝叶斯APC建模与预测封装INLA逻辑底层推断INLA提供嵌套拉普拉斯近似的贝叶斯推断引擎数据读取readxl / openxlsx读取GBD导出的xlsx文件数据处理dplyr / tidyr筛选、分组、长宽表转换日常高频大数据读取data.table几十万行CSV用fread读速度快很多可视化ggplot2重画预测曲线满足期刊投稿需求2.3 关于“包版本锁死”的心理准备这点有点像做生物信息时遇到Python环境一样。BAPC依赖INLAINLA又高度依赖R版本有时候你半年前能跑通的脚本升级R后突然报错。所以我建议直接把R版本、INLA版本、BAPC版本记录在项目文档里必要时用renv固定R包。我踩过的坑是为了跑新版INLA升级R之后BAPC包的某个函数开始报“unable to find an inherited method”最后只能降级R或从GitHub装开发版BAPC才解决。所以版本管理越早开始越好尤其是这种面向论文的统计流程。3. 从GBD数据到BAPC模型实操过程全记录3.1 GBD Results Tool数据下载的字段建议首先到GBD Results Tool选择GBD估计版本我一般选最新一轮比如GBD 2021或GBD 2024。然后在下载页面设置Cause选目标疾病Location选Global或具体国家Age选5-year age groupsSex选Male/Female/BothYear选历史区间比如1990-2019Measure选Deaths或IncidenceMetric选Number最后输出CSV。这里有两个容易忽略的字段。一是Metric如果选Rate得到的是每10万人的率不能直接作为BAPC的y二是GBD结果中其实没有直接给population。为了凑齐BAPC需要的offset我的做法是再下载同一配置下MetricRate的结果然后用number/rate乘以100000还原人口数或者去单独下载population。这个操作虽然笨但能确保年龄别、年份别完全对齐。3.2 关键一步整理成age、period、cohort、y、popBAPC需要的输入本质上很简单每个年龄组、每个时期对应的事件数和人群暴露数再附带队列信息。下面是核心数据处理代码。library(data.table) library(dplyr) library(tidyr) # 读取GBD事件数假设文件里有cause_name、location_name、sex_name、 # age_name、year、val等列 gbd_death - fread(GBD_Deaths_Number.csv, data.table FALSE) gbd_rate - fread(GBD_Deaths_Rate.csv, data.table FALSE) df - gbd_death %% select(age_name, year, number val) %% left_join( gbd_rate %% select(age_name, year, rate val), by c(age_name, year) ) %% mutate(pop round(number / rate * 100000)) # 把年龄组名称转成组中点 df$age_mid - case_when( df$age_name 0-4 years ~ 2.5, df$age_name 5-9 years ~ 7.5, df$age_name 10-14 years ~ 12.5, df$age_name 15-19 years ~ 17.5, # 其余年龄组按5岁一组继续填 df$age_name 85-89 years ~ 87.5, df$age_name 90-94 years ~ 92.5, df$age_name 95 years ~ 97.5, TRUE ~ NA_real_ ) # 计算队列队列约等于 period - age_mid apc_df - df %% filter(!is.na(age_mid)) %% mutate(age age_name, period year, cohort period - age_mid, y round(number), pop pop) %% select(age, period, cohort, y, pop)这里有两个细节要特别注意。一是GBD的Number估计值可能是小数比如12.34泊松计数模型一般要求整数所以这里round()二是95年龄组没有真实中点我一般取97.5也可以做敏感性分析取100或95。整理完数据后用unique()检查一下年龄组名称确保没有“All ages”和“1 year”之类混进来。3.3 模型拟合与未来预测数据整理好之后就要进入核心建模环节。BAPC包的建模流程一般会经历“创建APC对象”和“预测计算”两个阶段具体函数名在不同版本间可能有调整所以我建议不要凭记忆手写参数先跑通包自带的示例数据再把apc_df替换成自己的数据。library(BAPC) library(INLA) # 如果版本较新请先查看包自带说明 vignette(BAPC) # 基于历史版的一套常用写法旧版BAPC可以参考 # fit - compute.bayesrisk(apc_df, # agegroup apc_df$age, # period apc_df$period, # model APC) # summary(fit)你说这有点模糊现实就是这样R包版本迭代后函数名和参数都会变最稳的办法是用包自带的示例数据跑通流程再替换成自己的数据。预测年限通常看需求比如历史数据到2019年预测到2035年或2040年。预测年限太长可信区间会宽得没有参考价值太短审稿人又会质疑前瞻性。临床上常见做法是外推10到15年。3.4 画一张能放进论文的趋势预测图BAPC自带plot能快速看拟合效果但出版级图还是要自己画。大致思路是把模型的预测后验均值和95%可信区间整理成数据框再配合ggplot2做分面图。library(ggplot2) res - as.data.frame(fit$summary) # 具体结构以实际输出为准 ggplot(res, aes(x period)) geom_ribbon(aes(ymin lower, ymax upper), alpha 0.2) geom_line(aes(y mean)) labs(x Year, y Risk) theme_minimal()如果按年龄组分面建议把历史观测点画成散点预测部分用虚线并在图例里明确标注。预测区间一般会越宽越正常这是模型对外推不确定性的如实反映画图时注意y轴范围不要被极端区间拉伸该截断就截断。还需要提醒一点fit$summary只是示例结构不同版本返回对象字段名可能有差异先names(fit)查看再取列。画图虽然费时间但预测图往往是文章里最抢眼的那张值得多花点功夫。4. 常见问题和排查技巧实录4.1 INLA装不上十有八九是仓库地址或R版本问题INLA不在CRAN上很多人第一次装就卡住。常规安装命令是install.packages(INLA, repos c(https://inla.r-inla-download.org/R/stable, getOption(repos)), dependencies TRUE)常见情况是Windows下网络受限或者R版本太老导致仓库中找不到匹配版本。如果装不上去INLA官网下载源码包手工安装如果还不行就升级R到官方建议版本。注意INLA依赖不少最好一次把dependenciesTRUE加上。4.2 报错指向数据先检查age和cohort最常见的错误是age或者cohort是字符型。BAPC一般会按因子处理分组效应如果age列仍然是“0-4 years”这种文本某些版本会直接报错或把它当成无序因子。解决方案是把age和period转成有序因子并且确保age_mid转换没有遗漏。另一个坑是cohort为NA很大原因是age_name没有匹配上age_mid。用unique()检查一下实际的年龄组写法不要想当然。4.3 预测结果太离谱怎么从模型端回查不妨先看历史段的拟合值是否贴合观测值。BAPC拟合不好常见原因有几个一是数据里只有近几年时期短队列效应根本识别不了二是年龄组太少比如只给了0-4、5-9、10-14三个组模型当然不稳定三是某几个时期存在异常突变随机游走先验会被拉歪。处理思路通常是缩短预测年限、调整先验平滑参数或者改用RW1先验试试。如果是单一疾病且事件数很小可以把年龄组适当合并但要注意合并后的组中点设定。别急着质疑模型多数情况下是输入数据结构不对。5. 这些包用久了最想提醒你的事我刚开始接触这套流程时在INLA安装和BAPC包版本上卡了整整两个晚上后来经验是任何可能升级R或包的情况出现前先用本文还有配套的精品资源点击获取