在R中基于用药天数生成患者覆盖天数指标(tidyverse优先)
解决方案(基于tidyverse)
针对你的需求,我们可以通过宽长格式转换+日期序列生成+分组聚合的思路实现,同时兼顾60万+患者的大数据量效率:
1. 加载依赖包
library(tidyverse) library(lubridate)
2. 原始数据宽转长
先把日期列转为长格式,方便逐个处理每个日期的用药剂量:
df_long <- df %>% pivot_longer( cols = starts_with("2023"), # 匹配所有日期列 names_to = "date", values_to = "dose" ) %>% mutate(date = ymd(date)) # 转为标准日期格式
3. 生成药物覆盖日期序列
对每个非0剂量,生成「当日+后续N-1天」的覆盖日期,同时截断到数据的最大日期(避免超出时间范围):
max_date <- max(df_long$date) # 提前提取全局最大日期,提升效率 df_coverage <- df_long %>% filter(dose > 0) %>% mutate( end_date = pmin(date + days(dose - 1), max_date), # 截断结束日期 coverage_date = map2(date, end_date, ~seq(.x, .y, by = "day")) # 生成日期序列 ) %>% unnest(coverage_date) %>% select(pat, drug, coverage_date) %>% mutate(covered = 1)
4. 转回宽格式得到药物级覆盖(df2)
将长格式的覆盖数据转回宽格式,补全缺失的日期列并填充0:
df2 <- df_coverage %>% pivot_wider( id_cols = c(pat, drug), names_from = coverage_date, values_from = covered, values_fill = 0 ) %>% right_join(df %>% select(pat, drug), by = c("pat", "drug")) %>% # 补全所有pat-drug组合 mutate(across(starts_with("2023"), ~replace_na(.x, 0))) %>% arrange(pat, drug)
5. 聚合得到患者级覆盖(df3)
按患者分组,每个日期只要有任意一种药物覆盖,就标记为1:
df3 <- df2 %>% group_by(pat) %>% summarise(across(starts_with("2023"), ~max(.x)), .groups = "drop")
6. 计算覆盖天数占比
df3_with_ratio <- df3 %>% rowwise() %>% mutate( total_days = ncol(.) - 1, # 排除pat列的总天数 covered_days = sum(c_across(starts_with("2023"))), coverage_ratio = round(covered_days / total_days, 4) # 保留4位小数 ) %>% ungroup()
大数据量优化建议
- 提前提取全局变量(如
max_date),避免重复计算 - 若内存压力大,可使用
dplyr::group_split()按患者分块处理,再合并结果 - 对于超大规模数据,可结合
arrow包处理磁盘上的大数据框,减少内存占用
内容的提问来源于stack exchange,提问作者wdefreit
相关产品推荐
相关产品推荐

