如何使用dplyr根据第二个数据框更新第一个数据框?
用dplyr实现按年份规则更新数据框
问题说明
我们需要用second_df的数据更新first_df:first_df的t1/t2/t3/t4分别对应2024/2025/2026/2027年;更新规则为:second_df中每个ShortName对应的Year,需将first_df里该年份及之后的列值替换为对应的Value。
原始数据框代码
library(dplyr) # 初始数据框 first_df <- data.frame( ShortName = c("A", "B", "C"), t1 = c(0, 0, 0 ), t2 = c(1, 1, 1), t3 = c(2, 2, 2), t4 = c(3, 3, 3) ) # 更新规则数据框 second_df <- data.frame( ShortName = c("A", "B", "C"), Year = c(2024, 2025, 2026 ), Value=c(0, 5, 10) )
解决方案代码
我们可以通过长格式转换-关联判断-宽格式还原的流程实现需求,需配合tidyr包的pivot_longer/pivot_wider函数:
library(tidyr) # 建立t列与年份的映射关系 year_mapping <- c(t1 = 2024, t2 = 2025, t3 = 2026, t4 = 2027) updated_result <- first_df %>% # 将t1-t4列转为长格式,方便统一处理 pivot_longer( cols = starts_with("t"), names_to = "period", values_to = "original_val" ) %>% # 按ShortName关联更新规则数据 left_join(second_df, by = "ShortName") %>% # 匹配当前period对应的年份 mutate(current_year = year_mapping[period]) %>% # 应用更新规则:当前年份≥目标Year则替换为Value,否则保留原值 mutate(final_val = ifelse(current_year >= Year, Value, original_val)) %>% # 转回宽格式,恢复原数据结构 pivot_wider( id_cols = ShortName, names_from = "period", values_from = "final_val" ) %>% # 保持原数据的列顺序 select(ShortName, t1, t2, t3, t4) # 查看最终结果 print(updated_result)
运行结果
ShortName t1 t2 t3 t4 1 A 0 0 0 0 2 B 0 5 5 5 3 C 0 1 10 10
关键逻辑说明
- 长格式转换:把分散的年份列(t1-t4)转为统一的行记录,避免对每一列单独写更新逻辑;
- 年份匹配:通过预定义的映射关系,把
t开头的列名转为对应的年份值,方便后续判断; - 规则应用:用
ifelse判断当前年份是否符合更新条件,批量替换数值; - 宽格式还原:将处理后的长数据转回原有的宽格式结构,保持列顺序一致。
内容的提问来源于stack exchange,提问作者silent_hunter
相关产品推荐
相关产品推荐

