如何用tidyverse/dplyr链式优雅替换所有数值列NA为列均值?
无分组场景下用dplyr批量替换数值列NA为列均值的优雅写法
嘿,刚好处理过类似需求,给你分享个最贴合dplyr链式风格的优雅实现——核心就是用across()函数批量处理所有数值列,搭配coalesce()或者ifelse()完成NA替换,完全不用手动列每一列的名字:
推荐写法(dplyr 1.0.0+)
用across()配合coalesce(),语义清晰代码简洁:
dt %>% mutate(across(where(is.numeric), ~ coalesce(.x, mean(.x, na.rm = TRUE))))
where(is.numeric):自动筛选出所有数值类型的列,不管你的数据有多少数值列,都能自动适配coalesce(.x, mean(...)):coalesce函数会返回第一个非NA的值,逻辑直白:如果当前元素不是NA就保留原值,否则替换为该列的均值(na.rm = TRUE必须加,不然如果列里全是NA的话均值会变成NA,等于没替换)
如果你更习惯和之前单列写法一致的逻辑,也可以用ifelse()替代:
dt %>% mutate(across(where(is.numeric), ~ ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x)))
这个写法和你之前分组替换单列的逻辑完全对应,只是通过across()批量应用到了所有数值列。
旧版本兼容写法(dplyr < 1.0.0)
如果你的dplyr版本比较老,还没支持across(),可以用mutate_if():
dt %>% mutate_if(is.numeric, ~ ifelse(is.na(.x), mean(.x, na.rm = TRUE), .x))
不过现在官方已经推荐用across()替代mutate_if()这类函数了,新项目建议优先用上面的推荐写法。
内容的提问来源于stack exchange,提问作者hhh
相关产品推荐
相关产品推荐

