如何用R与dplyr为DataFrame添加基于另一表的指定N_1/N_2/N_3列?
解决方案
使用dplyr结合lubridate处理日期匹配,核心思路是先将宽格式的tab2转为长格式,再通过日期偏移(减1/2/3年)匹配对应的值:
library(dplyr) library(lubridate) # 原始数据 tab1 <- tribble( ~code, ~periode, ~prix, "a", "2023-01-01", 3, "b", "2023-01-01", 2, "c", "2023-02-01", 2, "d", "2023-02-01", 4 ) tab2 <- tribble( ~code, ~`2018-01-01`, ~`2018-02-01`, ~`2019-01-01`, ~`2019-02-01`, ~`2020-01-01`, ~`2020-02-01`,~`2021-01-01`, ~`2021-02-01`, ~`2022-01-01`, ~`2022-02-01`, "a", 2, 1, 2, 3, 3, 4, 1, 2, 2, 1, "b", 1, 2, 4, 2, 1, 2, 1, 5, 1, 2, "c", 2, 1, 5, 6, 1, 3, 4, 3, 1, 3, "d", 3, 2, 7, 8, 6, 4, 5, 9, 7, 8 ) # 将tab2转为长格式,便于日期匹配 tab2_long <- tab2 %>% pivot_longer(-code, names_to = "periode", values_to = "value") %>% mutate(periode = ymd(periode)) # 处理tab1,匹配N_1/N_2/N_3对应的值 result <- tab1 %>% # 转换日期格式,方便计算偏移 mutate(periode = ymd(periode)) %>% # 生成N_1/N_2/N_3对应的目标日期(分别减1/2/3年) mutate( N_1_periode = periode - years(1), N_2_periode = periode - years(2), N_3_periode = periode - years(3) ) %>% # 依次匹配对应日期的值 left_join(tab2_long, by = c("code", "N_1_periode" = "periode")) %>% rename(N_1 = value) %>% left_join(tab2_long, by = c("code", "N_2_periode" = "periode")) %>% rename(N_2 = value) %>% left_join(tab2_long, by = c("code", "N_3_periode" = "periode")) %>% rename(N_3 = value) %>% # 保留需要的列,并将日期转回字符格式 select(code, periode, prix, N_1, N_2, N_3) %>% mutate(periode = as.character(periode)) print(result)
代码说明
- 转换tab2格式:用
pivot_longer把宽格式的年份月份列转为长格式,每个code和日期对应一个数值,避免硬编码列名,适配所有月份的场景。 - 日期偏移计算:用
lubridate::years()实现年份减法,确保目标日期和原日期的月份一致。 - 匹配对应值:通过多次
left_join,根据code和目标日期匹配tab2_long中的值,最终得到需要的N_1/N_2/N_3列。
运行后输出结果与预期一致:
# A tibble: 4 × 6 code periode prix N_1 N_2 N_3 <chr> <chr> <dbl> <dbl> <dbl> <dbl> 1 a 2023-01-01 3 2 1 3 2 b 2023-01-01 2 1 1 1 3 c 2023-02-01 2 3 3 3 4 d 2023-02-01 4 8 9 4
内容的提问来源于stack exchange,提问作者Damien Dotta
相关产品推荐
相关产品推荐

