web-dev-qa-db-fra.com

Modification des niveaux de facteur avec dplyr mutate

C'est probablement simple et je me sens stupide de demander. Je veux changer les niveaux d'un facteur dans une trame de données, en utilisant mutate. Exemple simple:

library("dplyr")
dat <- data.frame(x = factor("A"), y = 1)
mutate(dat,levels(x) = "B")

Je reçois:

Error: Unexpected '=' in "mutate(dat,levels(x) ="

Pourquoi ça ne marche pas? Comment puis-je changer les niveaux de facteur avec la mutation?

41
user3393472

Avec le paquetage forcats du paquetage tidyverse , c'est aussi facile.

mutate(dat, x = fct_recode(x, "B" = "A"))
41
dpprdan

Je ne suis pas certain de bien comprendre votre question, mais si vous souhaitez modifier les niveaux de facteur de cyl avec mutate(), vous pouvez le faire:

df <- mtcars %>% mutate(cyl = factor(cyl, levels = c(4, 6, 8)))

Vous auriez:

#> str(df$cyl)
# Factor w/ 3 levels "4","6","8": 2 2 1 2 3 2 3 1 1 2 ...
32
Steven Beaupré

Peut-être recherchez-vous cette fonction plyr :: revalue:

mutate(dat, x = revalue(x, c("A" = "B")))

Vous pouvez aussi voir plyr :: mapvalues.

22
Diego

Vous pouvez utiliser la fonction recode de dplyr.

df <- iris %>%
     mutate(Species = recode(Species, setosa = "SETOSA",
         versicolor = "VERSICOLOR",
         virginica = "VIRGINICA"
     )
)
14
Stefano

Je ne peux pas commenter car je n'ai pas assez de points de réputation, mais recode ne fonctionne que sur un vecteur. Le code ci-dessus dans la réponse de @ Stefano devrait donc être

df <- iris %>%
  mutate(Species = recode(Species, 
     setosa = "SETOSA",
     versicolor = "VERSICOLOR",
     virginica = "VIRGINICA")
  )
12
code_cowboy

D'après ma compréhension, la réponse actuellement acceptée ne modifie que l'ordre des niveaux de facteur et non les libellés réels (c.-à-d. comment les niveaux du facteur sont appelés). Pour illustrer la différence entre les étiquettes et , considérons l'exemple suivant:

Convertissez cyl en facteur (il ne serait pas nécessaire de spécifier les niveaux car ils sont codés par ordre alphanumérique):

    mtcars2 <- mtcars %>% mutate(cyl = factor(cyl, levels = c(4, 6, 8))) 
    mtcars2$cyl[1:5]
    #[1] 6 6 4 6 8
    #Levels: 4 6 8

Changer l'ordre de niveaux (mais pas les étiquettes elles-mêmes: cyl est toujours la même colonne)

    mtcars3 <- mtcars2 %>% mutate(cyl = factor(cyl, levels = c(8, 6, 4))) 
    mtcars3$cyl[1:5]
    #[1] 6 6 4 6 8
    #Levels: 8 6 4
    all(mtcars3$cyl==mtcars2$cyl)
    #[1] TRUE

Assigne new labels à cyl L'ordre des étiquettes était le suivant: c (8, 6, 4), nous spécifions donc les nouvelles étiquettes comme suit:

    mtcars4 <- mtcars3 %>% mutate(cyl = factor(cyl, labels = c("new_value_for_8", 
                                                               "new_value_for_6", 
                                                               "new_value_for_4" )))
    mtcars4$cyl[1:5]
    #[1] new_value_for_6 new_value_for_6 new_value_for_4 new_value_for_6 new_value_for_8
    #Levels: new_value_for_8 new_value_for_6 new_value_for_4

Notez en quoi cette colonne diffère de nos premières colonnes:

    all(as.character(mtcars4$cyl)!=mtcars3$cyl) 
    #[1] TRUE 
    #Note: TRUE here indicates that all values are unequal because I used != instead of ==
    #as.character() was required as the levels were numeric and thus not comparable to a character vector

Plus de détails:

Si nous devions changer les niveaux de cyl en utilisant mtcars2 au lieu de mtcars3, nous aurions besoin de spécifier les étiquettes différemment pour obtenir le même résultat. L'ordre des étiquettes pour mtcars2 était: c (4, 6, 8), nous spécifions donc les nouvelles étiquettes comme suit

    #change labels of mtcars2 (order used to be: c(4, 6, 8)
    mtcars5 <- mtcars2 %>% mutate(cyl = factor(cyl, labels = c("new_value_for_4", 
                                                               "new_value_for_6", 
                                                               "new_value_for_8" )))

Contrairement à mtcars3$cyl et mtcars4$cyl, les étiquettes de mtcars4$cyl et mtcars5$cyl sont donc identiques, même si leurs niveaux ont un ordre différent.

    mtcars4$cyl[1:5]
    #[1] new_value_for_6 new_value_for_6 new_value_for_4 new_value_for_6 new_value_for_8
    #Levels: new_value_for_8 new_value_for_6 new_value_for_4

    mtcars5$cyl[1:5]
    #[1] new_value_for_6 new_value_for_6 new_value_for_4 new_value_for_6 new_value_for_8
    #Levels: new_value_for_4 new_value_for_6 new_value_for_8

    all(mtcars4$cyl==mtcars5$cyl)
    #[1] TRUE

    levels(mtcars4$cyl) == levels(mtcars5$cyl)
    #1] FALSE  TRUE FALSE
9
Flo