如何使用dplyr批量将质控列为指定值的对应数值列设为NA
问题描述
我有一个包含多列数值数据的dataframe,每列数值数据都对应有配对的质控列。如下示例中,dat是一个tibble对象,包含数值列v1、v3,分别配对质控列v1_a、v3_a,v2没有对应的质控列。
我需要实现如下需求:当v1_a、v3_a中的对应值为"A"或"D"时,将v1、v3的对应值设置为NA_real_。我希望得到基于dplyr、使用%>%管道符的实现方案,且该方案可扩展适配任意数量的数值-质控配对列。
示例数据
set.seed(10) dat <- tibble(v1 = runif(10) , v1_a = c("A", "A", NA, "B", NA, NA, NA, "D", NA, "A" ) , v2 = runif(10) , v3 = runif(10) , v3_a = c(NA, "A", "D", "B", NA, "A", NA, "A", NA, "A" )) dat #> v1 v1_a v2 v3 v3_a #> 1 0.53600 A 0.27529 0.354 NA #> 2 0.09315 A 0.22890 0.936 A #> 3 0.16980 NA 0.01438 0.246 D #> 4 0.90022 B 0.72931 0.473 B #> 5 0.42318 NA 0.24990 0.192 NA #> 6 0.74776 NA 0.16081 0.583 A #> 7 0.82346 NA 0.01698 0.459 NA #> 8 0.95523 D 0.48581 0.467 A #> 9 0.68522 NA 0.10279 0.400 NA #> 10 0.50125 A 0.80199 0.505 A
预期输出
#> v1 v1_a v2 v3 v3_a #> 1 NA A 0.27529 0.354 NA #> 2 NA A 0.22890 NA A #> 3 0.1698 NA 0.01438 NA D #> 4 0.9002 B 0.72931 0.473 B #> 5 0.4232 NA 0.24990 0.192 NA #> 6 0.7478 NA 0.16081 NA A #> 7 0.8235 NA 0.01698 0.459 NA #> 8 NA D 0.48581 NA A #> 9 0.6852 NA 0.10279 0.400 NA #> 10 NA A 0.80199 NA A
现有实现(逐列处理)
rmkQC <- c("A","D") # 需要筛除的质控值向量 dat %>% mutate(v1 = case_when(v1_a %in% rmkQC ~ NA_real_, TRUE ~ v1), v3 = case_when(v3_a %in% rmkQC ~ NA_real_, TRUE ~ v3))
我已经可以通过如下代码识别所有配对列:
colQC <- names(dat)[grep("_a" , names(dat))] colV <- sub("_a$","",colQC)
请问如何实现适配任意数量配对列的通用批量处理逻辑?
解答
使用dplyr::across()批量遍历数值列,结合动态列名引用即可实现通用逻辑,完全兼容管道写法:
library(dplyr) rmkQC <- c("A","D") dat_processed <- dat %>% mutate( across(all_of(colV), ~ case_when( .data[[paste0(cur_column(), "_a")]] %in% rmkQC ~ NA_real_, TRUE ~ .x )) )
逻辑说明
across(all_of(colV))遍历所有匹配到的带质控列的数值列,自动适配任意数量的配对列cur_column()获取当前正在处理的数值列名称,拼接_a后缀即可匹配到对应的质控列.data[[ ]]是dplyr提供的动态列引用代词,避免非标准评估导致的变量识别报错- 核心逻辑和你原有逐列
case_when的写法完全一致,仅做了批量封装
如果需要把配对列识别的逻辑也整合到管道中,可直接写成一站式实现:
rmkQC <- c("A","D") dat_processed <- dat %>% { colQC <- names(.)[grep("_a$", names(.))] colV <- sub("_a$", "", colQC) mutate(., across(all_of(colV), ~ case_when( .data[[paste0(cur_column(), "_a")]] %in% rmkQC ~ NA_real_, TRUE ~ .x ))) }
内容的提问来源于stack exchange,提问作者greengrass62
相关产品推荐
相关产品推荐

