基于分组生成累积随访时间与事件汇总表的技术实现问询
用dplyr实现随访年度汇总的解决方案
我来帮你搞定这个随访数据按年度汇总的需求!用dplyr完全能实现,我给你拆解步骤+代码示例,直接就能套用:
第一步:先明确核心逻辑
我们要达成的目标是:
- 生成1到20年的完整年度序列,每个年度对应结果的一行
- 对每个个体,判断其随访周期是否覆盖该年度,计算该个体在该年度的可用随访时长
- 按年度汇总所有个体的可用时长(
cmltime),以及该年度发生的事件总数(cmlevent)
第二步:代码实现(附示例数据)
先给你构造一份和你需求匹配的示例数据,你可以直接替换成自己的df1:
library(dplyr) library(tidyr) # 用到cross_join和replace_na工具 # 构造示例df1(已包含你提到的timeyrs和eventyr字段) set.seed(123) df1 <- tibble( ID = 1:10, startdate = as.Date("2010-01-01") + sample(0:365, 10), enddate = startdate + sample(365*3:365*18, 10), # 模拟3-18年的随访周期 eventdate = ifelse(runif(10) > 0.3, NA, startdate + sample(365*1:365*15, 10)) ) %>% mutate( # 取整随访总年数(和你的timeyrs逻辑一致) timeyrs = as.integer(difftime(enddate, startdate, units = "weeks")/52.25) %>% round(), # 取整事件发生的相对年份(和你的eventyr逻辑一致) eventyr = ifelse(!is.na(eventdate), as.integer(difftime(eventdate, startdate, units = "weeks")/52.25) %>% round(), NA) )
接下来是核心处理代码,生成你需要的df2:
# 生成1-20年的完整年度序列 annual_seq <- tibble(year = 1:20) # 生成目标数据集df2 df2 <- df1 %>% # 让每个个体和所有年度做交叉匹配,方便逐个年度计算贡献 cross_join(annual_seq) %>% # 过滤掉个体随访未覆盖到的年度(比如某人只随访5年,就排除6-20年) filter(year <= timeyrs) %>% # 计算该个体在当前年度的可用时长: # 这里简化为完整年度计1,如果你需要精确到天的时长,替换成下面注释的代码 mutate( annual_contribution = 1 # 精确时长版本(计算实际随访天数转成年份): # annual_contribution = as.numeric(pmin(enddate, startdate + years(year)) - pmax(startdate, startdate + years(year-1))) / 365.25 ) %>% # 按年度分组汇总 group_by(year) %>% summarise( cmltime = sum(annual_contribution, na.rm = TRUE), # 年度总可用随访时长 cmlevent = sum(eventyr == year, na.rm = TRUE) # 年度事件发生总数 ) %>% # 确保1-20年全部出现在结果里,无数据的年度自动填充0 right_join(annual_seq, by = "year") %>% replace_na(list(cmltime = 0, cmlevent = 0)) %>% arrange(year)
关键步骤说明
cross_join:把每个个体和所有年度配对,这样我们能对每个年度单独计算每个个体的贡献值filter(year <= timeyrs):只保留个体随访覆盖的年度,避免无效计算- 时长计算:默认用完整年度计数,如果你需要更精确的实际随访时长,就用注释里的代码,它会计算每个个体在该年度的实际随访天数再转成年份
right_join+replace_na:保证即使某个年度没有任何随访数据,也会在df2里显示一行,cmltime和cmlevent自动设为0,完美匹配你要的20行完整结果
内容的提问来源于stack exchange,提问作者sar
相关产品推荐
相关产品推荐

