如何用dplyr为含不同数据类型列的数据集标记全NA行?
标记指定列全为NA的行(含数值型和字符型混合列)
问题场景
当数据集指定列全为数值型时,用dplyr的rowwise()+c_across()可以轻松标记全NA行,但如果指定列同时包含数值型和字符型,直接运行会因类型无法合并报错。
比如这个混合类型数据集:
df <- data.frame(a = c(1,4,5,NA), b = c(NA,"ava","dillion",NA), c = c(3,7,8,NA), d = c(2,1,1,1))
运行原代码会抛出错误:
Error in `mutate()`: ℹ In argument: `allNA = case_when(...)`. ℹ In row 1. Caused by error in `case_when()`: ! Failed to evaluate the left-hand side of formula 1. Caused by error in `vec_c()`: ! Can't combine `a` <double> and `b` <character>. Run `rlang::last_trace()` to see where the error occurred.
解决方案
方法1:用rowSums结合across
不需要rowwise(),直接通过计算每行指定列的NA数量是否等于列数来判断:
library(dplyr) df %>% mutate(allNA = case_when( rowSums(is.na(across(a:c))) == ncol(across(a:c)) ~ "allNA", TRUE ~ "notAllNA" ))
输出结果:
a b c d allNA 1 1 <NA> 3 2 notAllNA 2 4 ava 7 1 notAllNA 3 5 dillion 8 1 notAllNA 4 NA <NA> NA 1 allNA
方法2:改进rowwise+c_across的写法
问题出在c_across会尝试合并不同类型的列,改用across配合purrr::every来逐列检查NA状态:
library(dplyr) library(purrr) df %>% rowwise() %>% mutate(allNA = case_when( every(across(a:c), is.na) ~ "allNA", TRUE ~ "notAllNA" )) %>% ungroup()
该方法避免了类型合并冲突,同样能得到正确结果。
方法3:用基础R的apply函数
如果不想依赖dplyr,可以用基础R函数实现:
df$allNA <- ifelse(apply(df[, c("a","b","c")], 1, function(x) all(is.na(x))), "allNA", "notAllNA")
内容的提问来源于stack exchange,提问作者llewmills
相关产品推荐
相关产品推荐

