R语言中基于多条件分组筛选DataFrame行的技术求助
按ID分组的多条件DataFrame行筛选解决方案
完整代码实现
library(dplyr) # 示例数据 df <- data.frame(ID = rep(c(479,147,643,228,501), c(3,3,1,2,2)), No = c("A009145","A009146","0","A146754",NA,"A156764",NA,NA,NA,NA,NA), Date = c("2012-06-28","2020-01-10","2020-01-10","2014-11-28",NA,NA,"2019-04-13","2017-10-27","2017-12-01",NA,NA), point = c(25.2,31.1,31.1,21.5,18.6,18.6,27.77,18.52,18.52,26.3,26.3)) # 执行筛选逻辑 result <- df %>% mutate(Date = as.Date(Date)) %>% group_by(ID) %>% filter( # 规则3:组内No和Date均为NA,保留所有行 (all(is.na(No)) & all(is.na(Date))) | # 规则2:组内所有No为NA,保留Date最新的行 (all(is.na(No)) & any(!is.na(Date)) & Date == max(Date, na.rm = TRUE)) | # 规则1:组内存在有效No(非NA且≠"0"),保留这些行中Date最新的 (!is.na(No) & No != "0" & Date == max(Date[!is.na(No) & No != "0"], na.rm = TRUE)) ) %>% ungroup() print(result)
输出结果
ID No Date point 1 479 A009146 2020-01-10 31.1 2 147 A146754 2014-11-28 21.5 3 643 NA 2019-04-13 27.77 4 228 NA 2017-12-01 18.52 5 501 NA <NA> 26.3 6 501 NA <NA> 26.3
逻辑解释
针对每个ID分组,按以下优先级判断筛选规则:
- 规则1(存在有效No):先筛选出
No不为NA且不等于"0"的行,再在这些行中保留Date最新的记录(na.rm=TRUE忽略Date为NA的无效行)。对应ID479、147的分组。 - 规则2(全No为NA但有有效Date):当组内所有
No都是NA,但存在非NA的Date时,保留Date最大的那一行。对应ID228、643的分组。 - 规则3(全No和Date为NA):当组内所有
No和Date都是NA时,保留所有行。对应ID501的分组。
原代码问题分析
原代码直接通过filter(!(No == "0" | is.na(No)))过滤掉了No为NA或"0"的行,导致:
- 所有
No全为NA的分组(228、643、501)被完全排除 - 未处理
Date为NA的场景 - 未覆盖"全No和Date为NA则保留所有行"的规则
内容的提问来源于stack exchange,提问作者Alegría
相关产品推荐
相关产品推荐

