1
votes

Remplacez manquant pour toutes les variables catégorielles par «Aucun»

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) )


0 commentaires

5 Réponses :


0
votes

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" .


1 commentaires

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



2
votes

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


0 commentaires

1
votes

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 
})


0 commentaires

0
votes

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)


1 commentaires

Cela ne fonctionne que s'il est acceptable que tout dans le bloc de données soit converti en facteurs.



0
votes

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 >


0 commentaires