假设我有一个包含许多列的数据框:var1
,...,var100
,还有一个长度相同的匹配命名向量。我想创建一个函数,如果在数据帧中有NA,它将从命名向量中选取数据。这是我到目前为止写的:
data %>%
mutate(var1 = ifelse(is.na(var1), named_vec["var1"], var1),
var2 = ifelse(is.na(var2), named_vec["var2"], var2),
...)
它可以工作,但是如果我有100的变量,那么编写这么多条件将是非常不切实际的。然后我尝试了这个:
data %>%
mutate_if(~ifelse(is.na(.x), named_vec[colnames(.x)], .x))
Error in selected[[i]] <- eval_tidy(.p(column, ...)) :
more elements supplied than there are to replace
但是这不起作用。 dplyr中有没有一种方法可以提取列名,可以对命名的向量进行切片?
这里有一个小的数据示例
data <- data.frame(var1 = c(1, 1, NA, 1),
var2 = c(2, NA, NA, 2),
var3 = c(3, 3, 3, NA))
named_vec <- c("var1" = 1, "var2" = 2, "var3" = 3)
使用coalesce
可能更容易做到这一点>
library(dplyr) library(purrr) library(stringr) nm1 <- str_c('var', 1:3) data[nm1] <- map_dfc(nm1, ~ coalesce(data[[.x]], named_vec[.x])) data # var1 var2 var3 #1 1 2 3 #2 1 2 3 #3 1 2 3 #4 1 2 3
[另一种选择是转换为'long'格式,然后对[value]列进行
left_join
,coalesce
,然后重新调整为'wide'格式
library(tidyr)
data %>%
mutate(rn = row_number()) %>%
pivot_longer(cols = -rn) %>%
left_join(enframe(named_vec), by = 'name') %>%
transmute(rn, name, value = coalesce(value.x, value.y)) %>%
pivot_wider(names_from = name, values_from = value) %>%
select(-rn)