如何在mutate中用case_when处理含NA列的两种场景问题
解决case_when处理全NA列报错的问题
问题场景
需要处理两种数据列场景:
- 列中同时包含NA和有效值
- 列仅包含NA
使用mutate结合case_when批量处理时,全NA列会触发报错,原示例代码如下:
case_1 <- tibble("a" = c("a","a", "a","a"), "b" = c(NA,"b", NA,"b")) case_2 <- tibble("a" = c("a","a", "a","a"), "b" = c(NA,NA,NA,NA)) case_1 <- case_1 %>% mutate("a" = case_when(!is.na(a) ~ a, is.na(a) ~ na.omit(unique(a))), "b" = case_when(!is.na(b) ~ b, is.na(b) ~ na.omit(unique(b)))) case_2 <- case_2 %>% mutate("a" = case_when(!is.na(a) ~ a, is.na(a) ~ na.omit(unique(a))), "b" = case_when(!is.na(b) ~ b, is.na(b) ~ na.omit(unique(b))))
其中case_1运行正常,case_2执行报错。
报错原因
当列全为NA时,na.omit(unique(b))会返回空向量,而case_when要求每个分支返回的向量长度必须和输入列一致(此处为4行),空向量无法匹配长度,因此触发错误。
解决方案
方法1:封装自定义处理函数
写一个可复用的函数,先判断列是否存在非NA值,再执行填充逻辑:
fill_na_with_unique <- function(x) { # 提取列中的非NA唯一值 unique_non_na <- unique(na.omit(x)) # 若无有效非NA值,直接返回原列;否则用唯一值填充NA if (length(unique_non_na) == 0) { x } else { case_when(!is.na(x) ~ x, TRUE ~ unique_non_na) } }
在mutate中调用该函数即可:
case_1 <- case_1 %>% mutate(a = fill_na_with_unique(a), b = fill_na_with_unique(b)) case_2 <- case_2 %>% mutate(a = fill_na_with_unique(a), b = fill_na_with_unique(b))
方法2:在case_when中确保返回长度匹配
直接在case_when分支里,将空向量转换为和列长度一致的NA向量:
case_2 <- case_2 %>% mutate( a = case_when( !is.na(a) ~ a, TRUE ~ rep(coalesce(na.omit(unique(a)), NA), length(a)) ), b = case_when( !is.na(b) ~ b, TRUE ~ rep(coalesce(na.omit(unique(b)), NA), length(b)) ) )
coalesce会在na.omit(unique(b))为空时返回NA,rep将其重复为和列长度一致的向量,满足case_when的长度要求。
效果验证
两种方法都能让case_1和case_2正常运行:
case_1的b列NA会被填充为"b"case_2的b列保持全NA,a列无变化
内容的提问来源于stack exchange,提问作者Camilo Montes
相关产品推荐
相关产品推荐

