Je souhaite convertir les valeurs manquantes de toutes les variables catégorielles de mon ensemble de données en "Aucune". J'ai plus de 100 variables de facteur et je veux le faire à la fois pour toutes sans utiliser leurs noms dans le code.
Supposons que je dispose de l'ensemble de données suivant (à titre d'exemple) et que je veuille remplacer 'NA' pour toutes les variables de facteur comme "x" et "y" ici avec "Aucun" comme niveau.
x = data.frame(x = as.factor(c(1, 2, NA, 3)), y = as.factor(c(NA, NA, 4, 5)), z=c(1,0,2,NA) )
5 Réponses :
Vous pouvez utiliser replace_na
du package tidyr
comme ceci:
library(tidyr) library(dplyr) x %>% mutate(x = as.character(x), y = as.character(y)) %>% replace_na(list(x = "None", y = "None"))
Notez que vous devez d'abord convertir les colonnes d'intérêt en caractères afin que le puisse contenir la chaîne "Aucun"
.
dans mes données réelles, j'ai des dizaines de variables catégorielles et ce sont tous des facteurs et je ne veux pas utiliser leurs noms dans le codage. J'espérais pouvoir utiliser quelque chose comme is.factor pour sélectionner toutes les variables de facteur
Une autre possibilité tidyverse
qui préserve la classe de facteurs:
x %>% mutate_if(is.factor, ~ fct_explicit_na(., na_level = "None")) x y z 1 1 None 1 2 2 None 0 3 None 4 2 4 3 5 NA
Vous pouvez convertir en caractère, remplacer et reconvertir en facteur, par exemple comme ceci:
df <- data.frame(x = as.factor(c(1, 2, NA, 3)), y = as.factor(c(NA, NA, 4, 5)), z=c(1,0,2,NA) ) isf <- sapply(df, is.factor) # check which columns are factors df[, isf] <- lapply(df[, isf], function(.){ levels(.) <- c(levels(.), "None") replace(., is.na(.), "None") })
Une version plus courte de la partie de travail:
df[, isf] <- lapply(df[, isf], function(.) factor(replace(as.character(.), is.na(.), "None")) )
Une autre stratégie (peut-être plus élégante) consiste à ajouter d'abord "Aucun "aux niveaux de chaque facteur, puis remplacez les NA
par "None"
:
df <- data.frame(x = as.factor(c(1, 2, NA, 3)), y = as.factor(c(NA, NA, 4, 5)), z=c(1,0,2,NA) ) isf <- sapply(df, is.factor) # check which columns are factors df[, isf] <- lapply(df[, isf], function(.){ . <- as.character(.) # convert to character .[is.na(.)] <- "None" # replace NA by "none" factor(.) # return a factor })
Voici une autre réponse sans aucun paquet. Il suffit de convertir en matrice et de convertir tout NA en 'None' et de le reconvertir en dataframe. C'est aussi rapide
x=as.matrix(data.frame(x = as.factor(c(1, 2, NA, 3)), y = as.factor(c(NA, NA, 4, 5)), z=c(1,0,2,NA) )) x[is.na(x)] = 'None' as.data.frame(x)
Cela ne fonctionne que s'il est acceptable que tout dans le bloc de données soit converti en facteurs.
Cela peut également être fait proprement dans la base R en utilisant rapply
:
library(dplyr) library(forcats) ## function to create simulated data.frame create_df <- function(df_size, prop_NA){ v <- sample(1:100, df_size^2, replace = TRUE) v[sample(seq_len(df_size^2), prop_NA * df_size^2)] <- NA data.frame(apply(matrix(v, ncol = df_size), 1, as.factor)) } ## rapply approach replace_NA_rapply <- function(dat) { rapply(dat, function(col) { if(any(is.na(col))) { col_na <- addNA(col) levels(col_na) <- c(levels(col), "None") col_na } else col }, classes = "factor", how = "replace") } ## tidyverse approach replace_NA_tidy <- function(dat) { mutate_if(dat, is.factor, ~ fct_explicit_na(., na_level = "None")) } ## benchmark several data.frame sizes bnch <- bench::press( df_size = c(10, 100, 1E3), prop_NA = c(0.05, 0.5), { dat <- create_df(df_size, prop_NA) bench::mark( rapply = replace_NA_rapply(dat), tidyverse = replace_NA_tidy(dat), min_iterations = 50 ) } ) bnch #> # A tibble: 12 x 8 #> expression df_size prop_NA min median `itr/sec` mem_alloc #> <bch:expr> <dbl> <dbl> <bch:tm> <bch:tm> <dbl> <bch:byt> #> 1 rapply 10 0.05 118.13µs 132.45µs 7274. 0B #> 2 tidyverse 10 0.05 1.67ms 1.82ms 529. 1.74MB #> 3 rapply 100 0.05 3.35ms 3.79ms 256. 1.25MB #> 4 tidyverse 100 0.05 18.93ms 20.36ms 48.2 1.34MB #> 5 rapply 1000 0.05 58.3ms 77.28ms 12.3 41.91MB #> 6 tidyverse 1000 0.05 260.24ms 291.22ms 3.40 52.88MB #> 7 rapply 10 0.5 253.2µs 286.64µs 3097. 0B #> 8 tidyverse 10 0.5 2.17ms 2.48ms 369. 1.91KB #> 9 rapply 100 0.5 3.07ms 3.58ms 272. 1005.53KB #> 10 tidyverse 100 0.5 18.59ms 19.58ms 50.7 1.12MB #> 11 rapply 1000 0.5 57.73ms 76.63ms 12.4 41.83MB #> 12 tidyverse 1000 0.5 249.06ms 319.42ms 3.08 54.53MB
## data dat <- data.frame(x = as.factor(c(1, 2, NA, 3)), y = as.factor(c(NA, NA, 4, 5)), z=c(1,0,2,NA)) ## rapply rapply(dat, function(col) { if(any(is.na(col))) { col_na <- addNA(col) levels(col_na) <- c(levels(col), "None") col_na } else col }, classes = "factor", how = "replace") #> x y z #> 1 1 None 1 #> 2 2 None 0 #> 3 None 4 2 #> 4 3 5 NA
p >