如何使用dplyr基于指定列子集是否存在NA值创建新指示列
最优解决方案(适配dplyr 1.0.4及以上版本)
直接使用if_any函数即可一行实现需求,这是当前dplyr针对行级多列判断的官方推荐写法:
library(tidyverse) # 生成无desired列的初始数据 df_start <- df %>% select(-desired) # 单管道生成desired列 df_result <- df_start %>% mutate(desired = as.integer(if_any(contains("test"), is.na)))
代码逻辑说明:
if_any第一个参数contains("test")选中所有列名含"test"的列- 第二个参数
is.na对选中列的每一个值做是否为NA的判断 - 只要同一行的选中列中存在至少一个NA,
if_any就返回TRUE,用as.integer转成整数就是1,否则返回FALSE转成0,完全匹配需求。
基于mutate(across())的兼容写法(适配dplyr 1.0.0及以上版本)
如果你使用的dplyr版本还没有支持if_any,可以用across结合rowSums实现:
df_result <- df_start %>% mutate(desired = as.integer(rowSums(across(contains("test"), ~is.na(.x))) > 0))
代码逻辑说明:
across(contains("test"), ~is.na(.x))把所有含"test"的列转成逻辑值:NA对应TRUE,非NA对应FALSErowSums对每行的逻辑值求和(逻辑值求和时TRUE算1,FALSE算0)- 求和结果大于0说明该行至少有一个NA,转整数后就是你需要的1/0标记。
老版本mutate_at写法(仅适配dplyr 1.0.0之前版本,不推荐新代码使用)
df_result <- df_start %>% mutate(desired = as.integer(rowSums(mutate_at(., vars(contains("test")), ~is.na(.)) %>% select(contains("test"))) > 0))
所有写法运行后得到的desired列和示例给出的结果完全一致,可通过all.equal(df_result$desired, df$desired)验证。
内容的提问来源于stack exchange,提问作者JasonAizkalns
相关产品推荐
相关产品推荐

