如何在R中用tidyverse扩展日期并生成累加变量新列
问题解决:按日期范围扩展并计算累加和
需求说明
基于data_a中的variable_x数值,按照data_b定义的每个year+treat组合的日期范围,先扩展出区间内的所有日期,再计算对应variable_x的累加和(cumsum)。
错误代码与报错
用户尝试的代码无法运行:
outcome <- data_b %>% group_by(year, treat) %>% mutate(id = 1:nrow(.)) %>% rowwise() %>% do(data.frame(id=.$id, days=seq(.$start_date,.$end_date,by="days"))) %>% mutate(cumsum_x = cumsum(data_a$variable_x[data_a$date %within% interval(start_date, end_date)]))
报错信息:
Error in `mutate()`: ! Problem while computing `id = 1:nrow(.)`. x `id` must be size 1, not 3. ℹ The error occurred in group 1: year = "year2019", treat = "treatA". Run `rlang::last_error()` to see where the error occurred.
错误原因
- 冗余的分组ID生成:
group_by(year, treat)后,每个分组仅对应data_b的一行数据,1:nrow(.)会生成长度为1的序列,但后续rowwise()与do()的组合打乱了分组逻辑,导致ID长度不匹配。 - 累加和计算逻辑错误:直接通过
data_a$variable_x[data_a$date %within% interval(start_date, end_date)]取整个区间的数值,未与扩展后的单个日期对应,导致长度不匹配。
正确解决方案
使用dplyr+lubridate+tidyr的组合,逻辑清晰且高效:
library(dplyr) library(lubridate) library(tidyr) # 生成每个日期范围的所有日期,展开后连接数据并计算累加和 outcome <- data_b %>% # 为每个日期区间生成日期序列,存储为列表列 mutate(days = map2(start_date, end_date, ~seq(.x, .y, by = "days"))) %>% # 展开列表列,将每个日期转为单独行 unnest(days) %>% # 与data_a按日期关联,获取对应variable_x数值 left_join(data_a, by = c("days" = "date")) %>% # 按year和treat分组,计算累加和 group_by(year, treat) %>% mutate(cumsum_x = cumsum(variable_x)) %>% ungroup()
运行后得到的outcome会包含每个year+treat组合下的所有日期,以及对应的variable_x和累加和cumsum_x。
内容的提问来源于stack exchange,提问作者Giuseppe Petri
相关产品推荐
相关产品推荐

