基于分组ID的配对字段筛选:识别版本时间不递增的log_id
解决R语言中筛选版本日期异常的log_id问题
我来帮你搞定这个需求!你要找的是那些按log_id分组后,存在高版本对应的日期早于低版本的异常ID,对吧?先说说你之前代码的问题:group_by之后直接用ifelse的写法不符合dplyr的语法逻辑,而且只对比了version=1和其他版本,没覆盖所有版本间的顺序检查,所以没法准确找出所有异常。
正确的解决方案(用dplyr实现)
首先先确认你的数据集:
x <- data.frame( "log_id" = c(16006,16006,16006,25109,25109,25109,25109,20506,20506), "status" = c(0,1,1,0,1,1,1,0,1), "version" = c(1,2,3,1,2,3,4,1,2), "date_time" = c( as.Date("2018-10-27"), as.Date("2019-01-06"), as.Date("2019-01-16"), as.Date("2018-10-27"), as.Date("2017-01-06"), as.Date("2019-02-17"), as.Date("2018-10-27"), as.Date("2019-01-12"), as.Date("2019-02-12") ) )
接下来用dplyr的分组+检查逻辑来找出异常ID:
library(dplyr) # 提取异常log_id到向量 abnormal_log_ids <- x %>% group_by(log_id) %>% # 每个组内按version从小到大排序 arrange(version, .by_group = TRUE) %>% # 检查是否存在任意一个高版本日期早于前一个版本的情况 summarise(has_abnormality = any(diff(date_time) < 0)) %>% # 筛选出有异常的组 filter(has_abnormality) %>% # 把log_id提取成向量 pull(log_id) # 查看结果 abnormal_log_ids
运行这段代码后,你会得到预期的结果:[1] 25109,完全符合你的需求。
代码逻辑解释
arrange(version, .by_group = TRUE):确保每个log_id组内的数据按version升序排列,这样我们可以依次检查相邻版本的日期顺序。diff(date_time):计算相邻日期的差值,如果差值小于0,说明后一个(更高版本)的日期比前一个早,违反了规则。any(diff(date_time) < 0):只要组内存在任何一次这样的异常,就标记该组为异常。pull(log_id):把筛选后的异常log_id提取成你需要的向量格式。
另一种实现思路
如果你想换一种方式检查,也可以通过对比version和date_time的排序顺序是否一致来判断:
abnormal_log_ids <- x %>% group_by(log_id) %>% summarise(is_abnormal = !all(order(version) == order(date_time))) %>% filter(is_abnormal) %>% pull(log_id)
这个逻辑是:如果version的排序顺序和date_time的排序顺序不完全一致,说明存在版本高但日期早的异常情况。
内容的提问来源于stack exchange,提问作者Spurryag
相关产品推荐
相关产品推荐

