求助:动态计算时间序列中客户产品的日期变量
解决方案:计算客户产品的替代时间与当前使用截止时间
针对需求中需要为每位客户和产品计算Date_replaced(产品被其他品类替代的时间点)和Date_current_until(产品作为当前使用产品的截止时间点),可以通过划分连续品类购买区块的方式实现动态查找,替代固定步长的lead()/lag()方法。
核心逻辑
- 按
Customer_ID分组,按Date排序购买记录 - 为每个客户的连续相同品类购买记录分配唯一组ID,区分不同的品类使用周期
- 针对每个品类组,获取下一个品类组的起始购买日期(即当前品类被替代的时间)
- 根据是否存在后续品类组,分别计算两个目标变量:
Date_replaced:下一个品类组的起始日期,无后续则为NADate_current_until:有后续品类组则取其起始日期,无后续则取客户最后一次购买的日期
实现代码(dplyr + data.table)
library(dplyr) library(data.table) # 原始数据构建 Customer_ID <- c(rep(1,4), rep(2,5)) Date <- c(seq(as.Date("2024-02-01"), as.Date("2024-02-04"), "days"), seq(as.Date("2024-02-01"), as.Date("2024-02-05"), "days")) Goods <- c(rep("Food",3), "Toys", "Newspaper", rep("Food",3), "Toys") Date_first_purchased <- c(rep("2024-02-01", 3), "2024-02-04", "2024-02-01", rep("2024-02-02", 3), "2024-02-05") %>% as.Date(., format="%Y-%m-%d") df <- data.frame(Customer_ID, Date, Goods, Date_first_purchased) # 计算目标变量 df_result <- df %>% group_by(Customer_ID) %>% arrange(Date, .by_group = TRUE) %>% # 为连续相同品类分配组ID mutate(goods_group = rleid(Goods)) %>% # 获取客户最后一次购买日期 mutate(customer_last_date = max(Date)) %>% # 按客户+品类组分组计算 group_by(Customer_ID, goods_group) %>% mutate( # 获取下一个品类组的起始日期 next_group_first_date = lead(first(Date), n = 1, default = NA), # 计算Date_replaced Date_replaced = next_group_first_date, # 计算Date_current_until Date_current_until = ifelse(is.na(next_group_first_date), customer_last_date, next_group_first_date) ) %>% ungroup() %>% # 清理中间变量 select(-goods_group, -customer_last_date, -next_group_first_date) # 查看结果 print(df_result)
无data.table的替代实现
如果不想依赖data.table,可以用dplyr原生函数生成品类组ID:
library(dplyr) df_result <- df %>% group_by(Customer_ID) %>% arrange(Date, .by_group = TRUE) %>% # 标记品类变化点,生成组ID mutate( goods_change = ifelse(is.na(lag(Goods)), TRUE, Goods != lag(Goods)), goods_group = cumsum(goods_change) ) %>% mutate(customer_last_date = max(Date)) %>% group_by(Customer_ID, goods_group) %>% mutate( next_group_first_date = lead(first(Date), n = 1, default = NA), Date_replaced = next_group_first_date, Date_current_until = ifelse(is.na(next_group_first_date), customer_last_date, next_group_first_date) ) %>% ungroup() %>% select(-goods_change, -goods_group, -customer_last_date, -next_group_first_date)
结果验证
运行代码后得到的df_result与示例数据中的Date_replaced和Date_current_until完全匹配,解决了固定步长函数无法动态查找替代时间的问题。
内容的提问来源于stack exchange,提问作者GRowInG
相关产品推荐
相关产品推荐

