You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言:按id分组,判断最近一个月的product_code是否为历史未出现值

问题:识别每个ID最近一个月是否出现新的产品编码

我有一个数据集,每个ID随时间会接收不同的product_code,date字段跨度近10年。需要识别每个ID在其product_code记录的最近一个月内,是否出现了历史记录中从未有过的product_code。

数据示例

原始数据创建代码

df <- data.frame(id=c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4),
           product_code=c("178","321","252","147","178","321","252","147","178","322","253","698",
                  "411","322","253","670"),
           date=c("2022-10-10","2022-10-10","2022-10-10","2022-10-10","2022-11-10","2022-11-10","2022-11-10",
                 "2022-11-10","2022-12-10","2022-12-10","2022-12-10","2022-12-10","2023-02-10",
                 "2023-02-10","2023-02-10","2023-02-10") )

按ID排序后的数据

df %>% arrange(id)
   id product_code       date
1   1          178 2022-10-10
2   1          178 2022-11-10
3   1          178 2022-12-10
4   1          411 2023-02-10
5   2          321 2022-10-10
6   2          321 2022-11-10
7   2          322 2022-12-10
8   2          322 2023-02-10
9   3          252 2022-10-10
10  3          252 2022-11-10
11  3          253 2022-12-10
12  3          253 2023-02-10
13  4          147 2022-10-10
14  4          147 2022-11-10
15  4          698 2022-12-10
16  4          670 2023-02-10

预期输出

id new_product_code
1                1
2                0
3                0
4                1

错误代码及问题分析

我尝试用以下代码但无法得到正确结果:

df %>% 
  group_by(id) %>% 
  mutate(new_product_code=if_else(any(product_code[date>max(date)-30]) %in%
                                    product_code[date<max(date)-30],1,0)) %>% 
  select(id,new_product_code)

问题出在三点:

  1. 日期类型未转换:原数据的date是字符串,max(date)-30会按字符串运算,无法得到正确的时间范围
  2. 逻辑判断反向:需求是检查最近一个月的编码是否有从未在历史出现过的,但代码判断的是最近一个月的编码是否在历史里,逻辑完全相反
  3. 结果处理错误:mutate会给每一行生成结果,最终会得到重复的ID记录,而我们需要每个ID一行的汇总结果

正确解决方案

先将date转换为日期类型,再分组后通过对比最近一个月和历史的产品编码集合来判断:

library(dplyr)

# 转换日期类型,分组处理
df %>%
  mutate(date = as.Date(date)) %>%
  group_by(id) %>%
  summarise(
    # 计算最近一个月的起始日期
    recent_month_start = max(date) - 30,
    # 提取最近一个月的所有产品编码(去重)
    recent_products = list(unique(product_code[date >= recent_month_start])),
    # 提取历史所有产品编码(最近一个月之前,去重)
    history_products = list(unique(product_code[date < recent_month_start])),
    # 判断是否有最近的产品不在历史中
    new_product_code = as.integer(any(!unlist(recent_products) %in% unlist(history_products)))
  ) %>%
  select(id, new_product_code)

运行后会得到完全符合预期的输出。

内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:43:08