求助:使用R语言dplyr按分组实现指定ifelse逻辑的问题
基于dplyr实现分组计算学生最终SCORE的正确方法
原始数据框HAVE
HAVE = data.frame( STUDENT = c(1,1,1,2,3,3,3,3,4,4), SCORE = c('PASS','MOD1','MOD2','MOD1','MOD2','MOD2','MOD1','ER','MOD2','ER') )
期望输出数据框WANT
WANT = data.frame( STUDENT = c(1,2,3,4), SCORE = c('PASS','MOD1','PASS','MOD2') )
分组计算规则
- 若分组内存在任意
SCORE为PASS,最终结果为PASS - 若分组内同时包含
MOD1和MOD2,最终结果为PASS - 若分组内仅包含
MOD1(无MOD2和PASS),最终结果为MOD1 - 若分组内仅包含
MOD2(无MOD1和PASS),最终结果为MOD2
问题分析
你之前的代码存在两个核心问题:
if_any(SCORE == 'PASS')用法错误,if_any需指定列名,且此处更适合用any(SCORE == 'PASS')判断分组内是否存在PASS- 嵌套
ifelse是逐行处理逻辑,无法实现分组级别的整体判断
正确的dplyr实现代码
library(dplyr) WANT <- HAVE %>% group_by(STUDENT) %>% summarise( SCORE = case_when( any(SCORE == 'PASS') ~ 'PASS', all(c('MOD1', 'MOD2') %in% SCORE) ~ 'PASS', any(SCORE == 'MOD1') ~ 'MOD1', any(SCORE == 'MOD2') ~ 'MOD2', TRUE ~ 'ER' # 兜底处理全为ER的极端情况 ), .groups = 'drop' # 计算完成后取消分组状态 )
代码解释
group_by(STUDENT):按学生ID进行分组summarise():对每个分组做聚合计算,每个分组生成一行结果case_when():按规则优先级依次判断:- 优先检查分组内是否存在
PASS,满足则返回PASS - 其次检查是否同时包含
MOD1和MOD2,满足则返回PASS - 接着检查是否存在
MOD1,满足则返回MOD1 - 再检查是否存在
MOD2,满足则返回MOD2 - 最后用
TRUE ~ 'ER'处理未覆盖的极端情况
- 优先检查分组内是否存在
.groups = 'drop':取消分组状态,得到普通数据框
内容的提问来源于stack exchange,提问作者bvowe
相关产品推荐
相关产品推荐

