如何在R中基于特定逻辑计算`date_first_boosted`变量?
在R语言中根据特定逻辑计算新增变量
数据准备
以下是生成示例数据框的代码:
df <- structure(list(master_id = c(100L, 100L, 102L, 102L, 600L, 600L, 800L, 800L, 800L), vaccination_id = c(19682164L, 26761757L, 21051316L, 26452487L, 20834063L, 26513056L, 20833333L, 26514589L, 26514501L), vaccine_name = c("JSN", "PFR", "JSN", "MOD", "JSN", "MOD", "JSN", "PFR", "PFR"), vaccine_code = c(212L, 208L, 212L, 207L, 212L, 207L, 212L, 208L, 208L), given_date = c("3/9/2021", "11/9/2021", "4/11/2021", "11/1/2021", "4/7/2021", "11/3/2021", "3/10/2021", "11/22/2021", "5/23/2022"), dose_number = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 3L)), class = "data.frame", row.names = c(NA, -9L))
数据框结构如下:
master_id vaccination_id vaccine_name vaccine_code given_date dose_number 1 100 19682164 JSN 212 3/9/2021 1 2 100 26761757 PFR 208 11/9/2021 2 3 102 21051316 JSN 212 4/11/2021 1 4 102 26452487 MOD 207 11/1/2021 2 5 600 20834063 JSN 212 4/7/2021 1 6 600 26513056 MOD 207 11/3/2021 2 7 800 20833333 JSN 212 3/10/2021 1 8 800 26514589 PFR 208 11/22/2021 2 9 800 26514501 PFR 208 5/23/2022 3
需求说明
需要新增date_first_boosted列,标记用户首次符合加强针条件的日期,判断逻辑满足以下任一组合即可:
- 3剂及以上PFR疫苗;
- 3剂及以上MOD疫苗;
- 3剂及以上MOD与PFR组合疫苗;
- 2剂及以上JSN疫苗;
- 2剂及以上JSN与PFR组合疫苗;
- 2剂及以上JSN与MOD组合疫苗;
期望输出如下:
master_id vaccination_id vaccine_name vaccine_code given_date dose_number date_first_boosted 1 100 19682164 JSN 212 3/9/2021 1 2 100 26761757 PFR 208 11/9/2021 2 11/9/2021 3 102 21051316 JSN 212 4/11/2021 1 4 102 26452487 MOD 207 11/1/2021 2 11/1/2021 5 600 20834063 JSN 212 4/7/2021 1 6 600 26513056 MOD 207 11/3/2021 2 11/3/2021 7 800 20833333 JSN 212 3/10/2021 1 8 800 26514589 PFR 208 11/22/2021 2 11/22/2021 9 800 26514501 PFR 208 5/23/2022 3 11/22/2021
解决方案代码
使用dplyr包完成分组计算,步骤如下:
- 转换日期格式确保排序逻辑正确;
- 按用户分组,按接种日期排序;
- 累计统计各类疫苗接种数量,判断是否满足加强针条件;
- 提取首次符合条件的日期并填充到用户所有后续行。
library(dplyr) df <- df %>% # 转换日期格式 mutate(given_date = as.Date(given_date, format = "%m/%d/%Y")) %>% # 按用户分组并按接种日期排序 group_by(master_id) %>% arrange(given_date, .by_group = TRUE) %>% # 累计统计各类疫苗接种量 mutate( total_jsn = cumsum(vaccine_name == "JSN"), total_pfr = cumsum(vaccine_name == "PFR"), total_mod = cumsum(vaccine_name == "MOD"), # 判断当前行是否符合加强针条件 is_boosted = case_when( total_pfr >= 3 ~ TRUE, total_mod >= 3 ~ TRUE, (total_pfr + total_mod) >= 3 ~ TRUE, total_jsn >= 2 ~ TRUE, (total_jsn + total_pfr) >= 2 ~ TRUE, (total_jsn + total_mod) >= 2 ~ TRUE, TRUE ~ FALSE ), # 标记首次符合条件的日期 date_first_boosted = ifelse(is_boosted, given_date, NA), # 将首次日期填充到用户所有后续行 date_first_boosted = first(date_first_boosted[is_boosted]) ) %>% # 转换回原日期字符串格式 mutate(given_date = format(given_date, "%m/%d/%Y"), date_first_boosted = ifelse(is.na(date_first_boosted), "", format(date_first_boosted, "%m/%d/%Y"))) %>% ungroup() %>% # 恢复原数据列顺序 select(master_id, vaccination_id, vaccine_name, vaccine_code, given_date, dose_number, date_first_boosted) # 查看结果 print(df, row.names = FALSE)
输出结果
运行代码后得到的结果与期望输出一致:
master_id vaccination_id vaccine_name vaccine_code given_date dose_number date_first_boosted 100 19682164 JSN 212 3/9/2021 1 100 26761757 PFR 208 11/9/2021 2 11/9/2021 102 21051316 JSN 212 4/11/2021 1 102 26452487 MOD 207 11/1/2021 2 11/1/2021 600 20834063 JSN 212 4/7/2021 1 600 26513056 MOD 207 11/3/2021 2 11/3/2021 800 20833333 JSN 212 3/10/2021 1 800 26514589 PFR 208 11/22/2021 2 11/22/2021 800 26514501 PFR 208 5/23/2022 3 11/22/2021
内容的提问来源于stack exchange,提问作者user3813620
相关产品推荐
相关产品推荐

