如何筛选特定服务发生且此前无其他服务的记录及6个月范围查询
筛选符合条件的服务记录解决方案
给定包含姓名、日期、服务的数据集,需要完成两个核心需求:
- 筛选出特定服务(如Surgery)发生,且该服务日期之前无其他服务的记录(示例中仅Bruce Wayne的Surgery符合条件)
- 将查询条件修改为:检查该服务日期前6个月内是否存在其他服务,再筛选符合条件的记录
先准备好可用于计算的数据集(原数据的日期是字符型,需转成日期格式):
Date <- c("2022-01-01","2022-04-01","2022-05-01","2022-07-01","2022-08-01","2022-08-05") Name <- c("John Doe","John Doe","John Doe","Jane Doe","Bruce Wayne","Bruce Wayne") Service <- c("Check-up","Surgery","Follow-up", "Check-up", "Surgery", "Follow-up") df <- data.frame(Date,Name,Service) # 转日期格式,后续才能做时间计算 df$Date <- as.Date(df$Date)
一、筛选特定服务且之前无任何服务的记录
思路
按姓名分组,把每个用户的服务按日期排序,只要筛选出「服务是Surgery,且是该用户的第一条服务」的记录就行。
dplyr 实现
library(dplyr) result1 <- df %>% group_by(Name) %>% arrange(Date) %>% filter(Service == "Surgery" & row_number() == 1) %>% ungroup() # 输出结果 result1
运行后会得到符合要求的第5行记录:
Date Name Service 1 2022-08-01 Bruce Wayne Surgery
Base R 实现
# 先按姓名+日期排序 df_sorted <- df[order(df$Name, df$Date), ] # 标记每个用户的第一条记录 df_sorted$is_first <- ave(df_sorted$Date, df_sorted$Name, FUN = function(x) seq_along(x) == 1) # 筛选目标记录 result1_base <- df_sorted[df_sorted$Service == "Surgery" & df_sorted$is_first == 1, ] rownames(result1_base) <- NULL result1_base
二、修改为检查服务日期前6个月内无其他服务
思路
对每条Surgery记录,计算它的日期往前推6个月的时间点,然后检查该用户的其他服务是否都在这个时间点之前,没有的话就保留这条记录。
dplyr 实现
result2 <- df %>% group_by(Name) %>% filter( Service == "Surgery", # 检查该用户所有非Surgery服务的日期,都在当前Surgery日期的6个月之前 all(ifelse(Service != "Surgery", Date < (Date - months(6)), TRUE)) ) %>% ungroup() result2
示例中Bruce Wayne的Surgery日期是2022-08-01,往前推6个月是2022-02-01,他之前没有其他服务,所以会被保留;John Doe的Surgery日期是2022-04-01,往前推6个月是2021-10-01,而他的Check-up在2022-01-01(在6个月区间内),所以会被排除。
Base R 实现
result2_base <- lapply(split(df_sorted, df_sorted$Name), function(user_df) { surgery_rows <- user_df[user_df$Service == "Surgery", ] if(nrow(surgery_rows) == 0) return(NULL) # 逐条检查Surgery记录是否符合条件 valid_rows <- sapply(1:nrow(surgery_rows), function(i) { surgery_date <- surgery_rows$Date[i] six_months_ago <- surgery_date - months(6) # 所有非Surgery服务的日期都早于6个月前 all(user_df$Date[user_df$Service != "Surgery"] < six_months_ago) }) surgery_rows[valid_rows, ] }) %>% do.call(rbind, .) rownames(result2_base) <- NULL result2_base
内容的提问来源于stack exchange,提问作者Indescribled
相关产品推荐
相关产品推荐

