вставить имена столбцов в dplyr

Предположим, у меня есть фрейм данных с множеством столбцов: 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)

person Marco De Virgilis    schedule 07.05.2020    source источник
comment
результат вашего неработающего кода также будет полезен   -  person Pablo Herreros Cantis    schedule 07.05.2020


Ответы (1)


Это может быть проще сделать с 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

Или, если мы реплицируем named_vec,

data[] <-  coalesce(as.matrix(data), named_vec[col(data)])

Другой вариант - преобразовать в «длинный» формат, затем сделать left_join, coalesce столбцы «значения» и вернуть форму в «широкий» формат.

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)
person akrun    schedule 07.05.2020
comment
Спасибо. Я решил с data %>% replace_na(as.list(named_vec)) - person Marco De Virgilis; 07.05.2020