如何用dplyr将全为0的分组中的0替换为NA?
解决全0分组替换为NA的问题
正确解决方案
直接用dplyr分组结合if/else就能实现需求,代码简洁高效:
library(dplyr) df <- tibble(key_1 = rep(1:2, each = 4), key_2 = rep(letters[1:2], each = 2, times = 2), value = c(0, 0, 0, -1, 1, 2, 1, 0)) df |> group_by(key_1, key_2) |> mutate(value = if (all(value == 0)) NA_real_ else value) |> ungroup() # 可选,按需取消分组
运行结果符合预期:
# A tibble: 8 × 3 key_1 key_2 value <int> <chr> <dbl> 1 1 a NA 2 1 a NA 3 1 b 0 4 1 b -1 5 2 a 1 6 2 a 2 7 2 b 1 8 2 b 0
修正你原有的case_when写法
你之前的错误源于case_when的规则:每个分支返回的长度必须一致。sum(value != 0) == 0是分组级的单逻辑值,对应返回的NA长度为1,但.default = value是分组内的多行数据(比如分组1a有2行,value长度为2),导致长度不匹配报错。
修正后的case_when写法:
df |> group_by(key_1, key_2) |> mutate(value = case_when( all(value == 0) ~ NA_real_, # 用all判断全0更直观,NA_real_匹配数值类型 .default = value ))
这里all(value == 0)直接判断分组是否全为0,NA_real_是数值型NA(和value列类型一致),当条件为真时,它会自动广播到分组的所有行,和.default的value长度匹配。
另一种替代方法:使用replace函数
如果习惯用replace,也可以这样实现:
df |> group_by(key_1, key_2) |> mutate(value = replace(value, all(value == 0), NA_real_))
内容的提问来源于stack exchange,提问作者uke
相关产品推荐
相关产品推荐

