dplyr使用mutate、last、ifelse分组计算CRP值结果异常排查
问题根因
你的代码有三处核心错误:
- 括号位置错误导致判断逻辑完全错位:
last(na.omit(CRP) < 8)的执行顺序是先逐元素计算CRP < 8得到布尔向量,再删除布尔向量中的缺失值取最后一位,完全不是你需要的「先提取所有非缺失CRP值,取最后一个值再判断是否小于8」的逻辑。 - 分支返回值不符合需求:当判断结果为「最后非缺失CRP不小于8」时,你直接返回了整列
CRP,会导致组内所有非缺失CRP都被填充到CRP2列,这就是b组出现重复有效值的原因。 - 未处理边界场景:如果某组CRP全为缺失值,
na.omit(CRP)会返回空向量,直接调用last会返回无意义的空值,直接导致c组这类存在特殊缺失分布的分组计算异常。
修正代码
library(dplyr) input %>% group_by(record_id) %>% mutate( # 定位组内最后一个非缺失CRP的行索引,无有效非缺失值时返回长度为0的空向量 last_valid_pos = tail(which(!is.na(CRP)), 1), last_valid_crp = if (length(last_valid_pos) == 0) NA_real_ else CRP[last_valid_pos], CRP2 = case_when( # 无有效CRP值 或 最后一个有效CRP<8:整组返回NA is.na(last_valid_crp) | last_valid_crp < 8 ~ NA_real_, # 仅最后一个有效CRP所在行保留原始值,其余行返回NA row_number() == last_valid_pos ~ CRP, TRUE ~ NA_real_ ) ) %>% select(-last_valid_pos, -last_valid_crp) # 移除中间辅助列
效果说明
- 最后一个非缺失CRP<8的分组:CRP2整组为NA,和你预期的a组结果一致
- 最后一个非缺失CRP>=8的分组:仅该非缺失值所在行保留原始CRP值,其余行均为NA,不会出现b组重复输出有效值的问题
- 存在任意缺失分布(包括全缺失)的分组:都能准确定位最后一个有效CRP值做判断,不会出现c组逻辑失效的问题
内容的提问来源于stack exchange,提问作者lecb
相关产品推荐
相关产品推荐

