基于双条件筛选ID:保留180天内购买不同车型的用户数据
问题描述
我创建了如下示例dataframe:
df <- data.frame(id = c(1,1,1,2,2,2,2,3,3), car = c("subaru", "audi", "subaru", "toyota", "toyota", "audi", "subaru", "nissan", "nissan"), buy_date = c("01/01/2000", "01/01/2001", "01/02/2001", "01/01/2000", "01/05/2000", "01/01/2005", "01/03/2005", "01/01/2000", "02/01/2000")) df$buy_date <- as.Date(df$buy_date, format="%d/%m/%Y") #此转换目前存在问题,但暂不关注
生成的数据框:
| id | car | buy_date |
|---|---|---|
| 1 | subaru | 2000-01-01 |
| 1 | audi | 2001-01-01 |
| 1 | subaru | 2001-02-01 |
| 2 | toyota | 2000-01-01 |
| 2 | toyota | 2004-12-01 |
| 2 | audi | 2005-01-01 |
| 2 | subaru | 2005-03-01 |
| 3 | nissan | 2000-01-01 |
| 3 | nissan | 2000-01-02 |
需求:针对每个ID,若该用户在180天内购买过两种不同类型的车型,则保留该ID对应的相关行。期望结果:
| id | car | buy_date |
|---|---|---|
| 1 | audi | 2001-01-01 |
| 1 | subaru | 2001-02-01 |
| 2 | toyota | 2004-12-01 |
| 2 | audi | 2005-01-01 |
| 2 | subaru | 2005-03-01 |
解决方案
方法1:使用dplyr的前后行比较
仅依赖dplyr包即可实现,逻辑简洁直接:
library(dplyr) result <- df %>% group_by(id) %>% arrange(buy_date) %>% # 标记当前行是否属于符合条件的记录组 mutate( # 检查当前行之后180天内是否存在不同车型 qualify = any((lead(buy_date, default = last(buy_date)+181) <= buy_date + 180) & (car != lead(car, default = car))), # 补充检查当前行之前180天内是否存在不同车型 qualify = qualify | any((lag(buy_date, default = first(buy_date)-181) >= buy_date - 180) & (car != lag(car, default = car))) ) %>% filter(qualify) %>% select(-qualify) %>% ungroup() print(result)
方法2:使用slider包的滑动窗口(更灵活)
如果需要更精准的时间范围判断,推荐使用slider包的滑动窗口功能,适配复杂场景:
library(dplyr) library(slider) result <- df %>% group_by(id) %>% arrange(buy_date) %>% # 检查当前日期前后180天窗口内是否存在不同车型 mutate(has_diff_car = slide_lgl( .x = car, .i = buy_date, .f = ~ length(unique(.x)) > 1, .before = 180, .after = 180 )) %>% filter(has_diff_car) %>% select(-has_diff_car) %>% ungroup() print(result)
两种方法均能得到期望结果,方法1适合基础场景,方法2更适配复杂时间窗口的判断需求。
内容的提问来源于stack exchange,提问作者Badboybørge
相关产品推荐
相关产品推荐

