R中用tidyverse为商品同周价格匹配上年同期值
tidyverse 实现“同商品同周度上一年同期价格匹配”的落地代码
这个需求的核心是严格匹配维度:同一GoodID、同一Week下,取当前行Year值减1对应的Price,无匹配项自动填NA,不需要先拆分筛数据,两种可直接复用的实现方式如下:
方法1:自左连接实现(完全匹配规则、无逻辑偏差)
这是最贴合你需求逻辑的写法,不受数据断档影响——哪怕同组下年份不连续,也只会取“恰好上一年”的价格,不会错配跨年度的旧数据。
实现逻辑是把原表复制为参照表,将参照表的Year值加1后,和主表按GoodID、Week、Year三个维度左连接,匹配不上的最早年份数据会自动填充NA。
# 构造用于匹配上年价格的参照表 ref_table <- df %>% select(GoodID, Week, Year, Price) %>% # 把参照表的年份+1,让它和主表的“当前观测年份”对齐: # 比如参照表里2015年的记录,偏移后Year=2016,就能匹配主表中2016年同GoodID同Week的行 mutate(Year = Year + 1) %>% rename(`Price last year` = Price) # 主表左连接参照表,自动生成目标列 df <- df %>% left_join(ref_table, by = c("GoodID", "Week", "Year"))
方法2:分组lag快速实现(适合同组年份完全连续的场景)
如果你的数据集保证每个GoodID、每个Week对应的年份是连续无断档的,可以用分组后取滞后值的方式快速实现,代码更简洁。
注意:使用前必须保证同组内的行按Year升序排列,否则lag会错取任意旧值;如果存在年份断档(比如某商品某周缺2016年数据、只有2015和2017年),这种方法会把2015年的价格错配给2017年的行,不符合“恰好上一年”的要求。
df <- df %>% # 按匹配维度分组:同商品同周度单独成组 group_by(GoodID, Week) %>% # 组内按年份升序排列,保证取到的是紧邻的上一年数据 arrange(Year, .by_group = TRUE) %>% # 取组内上一行的Price值,作为上一年同期价格 mutate(`Price last year` = lag(Price, n = 1)) %>% ungroup()
常见踩坑提醒
- 字段名大小写要和你的数据集完全一致:比如你之前的代码里把周数字段写成小写
week,就需要把代码里的Week同步替换为小写week,否则会因为字段不匹配生成全NA的列 - 之前用
filter拆分年份的写法存在本质问题:每次filter操作都会把数据集裁剪为单一年份的子集,直接丢失其他年份的观测值,根本无法把计算结果拼回完整原表
内容的提问来源于stack exchange,提问作者Leonard B
相关产品推荐
相关产品推荐

