R语言:匹配命名规则的多列全为NA时mutate生成新变量问题
问题原因
你写的代码不生效的核心问题是:vars(matches('pattern'))属于tidyselect列选择语法,无法直接在case_when的判断条件中逐行校验所有匹配列的取值状态,is.na()作用在列选择器上不会返回每行的匹配列是否全为NA的布尔结果,因此无法得到预期输出。
实现方案
方案1:使用if_all(dplyr 1.0.0及以上版本推荐)
if_all是dplyr官方提供的行维度判断函数,专门用于校验某行的所有选中列是否全部满足指定条件,完全适配你的需求:
library(dplyr) df <- df %>% mutate( column_to_create = case_when( # 所有匹配pattern的列均为NA时赋值为字符型"1" if_all(matches('pattern'), ~ is.na(.x)) ~ "1", # 不满足条件时的默认值,可根据需求调整 .default = NA_character_ ) )
如果不需要多分支判断,直接用ifelse写法更简洁:
df <- df %>% mutate( column_to_create = ifelse(if_all(matches('pattern'), is.na), "1", NA_character_) )
方案2:兼容低版本dplyr的rowSums实现
如果你使用的dplyr版本低于1.0.0没有if_all函数,可以通过统计每行非NA值的数量实现判断:
df <- df %>% mutate( # 统计每行匹配pattern的列的非NA值数量 non_na_count = rowSums(!is.na(across(matches('pattern')))), # 非NA数量为0说明全为NA,赋值为"1" column_to_create = ifelse(non_na_count == 0, "1", NA_character_) ) %>% select(-non_na_count) # 不需要中间计数列可删除
注意事项
- 如果你需要的是数值型的1而非字符型,直接去掉赋值内容的引号即可,对应默认值调整为
NA_real_。 - 不满足全NA条件时的取值可根据业务需求自行修改,比如赋值为0。
内容的提问来源于stack exchange,提问作者MLE
相关产品推荐
相关产品推荐

