Как заменить все значения ‹NA› в data.frame с помощью forcats::fct_explicit_na()?

У меня есть фрейм данных с 19 переменными, 17 из которых являются факторами. Некоторые из этих факторов содержат пропущенные значения, закодированные как NA. Я хотел бы перекодировать отсутствующие значения как отдельный уровень фактора «to_impute», используя forcats::fct_explicit_na() для всех факторов во фрейме данных.

Небольшой пример с двумя факторными переменными:

df <- structure(list(loc_len = structure(c(NA, NA, NA, NA, NA, NA, 
1L, 1L, 3L, 1L), .Label = c("No", "< 5 sec", "5 sec - < 1 min", 
"1 - 5 min", "> 5 min", "Unknown duration"), class = "factor"), 
    AMS = structure(c(1L, 2L, NA, 1L, 1L, NA, NA, NA, NA, NA), .Label = c("No", 
    "Yes"), class = "factor")), .Names = c("loc_len", "AMS"), row.names = c(NA, 
-10L), class = c("tbl_df", "tbl", "data.frame"))

table(df$loc_len, useNA = "always")

              No          < 5 sec  5 sec - < 1 min        1 - 5 min          > 5 min Unknown duration             <NA> 
               3                0                1                0                0                0                6 

Код ниже делает это для двух переменных. Я хотел бы сделать это для всех факторных переменных «f_names» во фрейме данных. Есть ли способ «векторизовать» fct_explicit_na()?

f_names <- names(Filter(is.factor, df))

 f_names
[1] "loc_len" "AMS"

Код ниже делает то, что я хочу, но отдельно для каждого фактора:

df_new <- df  %>% 
                    mutate(loc_len = fct_explicit_na(loc_len, na_level = "to_impute")) %>% 
                    mutate(AMS = fct_explicit_na(AMS, na_level = "to_impute"))

Мне нужны таблицы такого рода для всех факторов в наборе данных, имена в 'f_names' :

lapply(df_new, function(x) data.frame(table(x, useNA = "always")))

Сейчас:

$loc_len
                 x Freq
1               No    3
2          < 5 sec    0
3  5 sec - < 1 min    1
4        1 - 5 min    0
5          > 5 min    0
6 Unknown duration    0
7        to_impute    6
8             <NA>    0

$AMS
          x Freq
1        No    3
2       Yes    1
3 to_impute    6
4      <NA>    0

person user25494    schedule 17.03.2018    source источник
comment
Пожалуйста, покажите небольшой воспроизводимый пример и ожидаемый результат   -  person akrun    schedule 17.03.2018


Ответы (2)


Еще лучше, элегантное и идиоматическое решение, предоставленное:

https://github.com/tidyverse/forcats/issues/122

library(dplyr)
df = df %>% mutate_if(is.factor,
                      fct_explicit_na,
                      na_level = "to_impute")
person user25494    schedule 21.03.2018
comment
О да. Это очень аккуратно. - person Seanosapien; 28.04.2018

После некоторых проб и ошибок приведенный ниже код делает то, что я хочу.

library(tidyverse)

df[, f_names] <- lapply(df[, f_names], function(x) fct_explicit_na(x, na_level = "to_impute")) %>% as.data.frame
person user25494    schedule 19.03.2018