2015-01-28 18 views
24

Questo è probabilmente semplice e mi sento stupido a chiedere. Voglio cambiare i livelli di un fattore in un frame di dati, usando mutate. Esempio semplice:Modifica dei livelli dei fattori con dplyr mutate

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

ottengo:

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

Perché questo non funziona? Come posso cambiare i livelli dei fattori con mutate?

+3

Forse 'dat%>% mutare (x = fattore (x, etichette = 'B'))' A proposito, l'operatore tubo non è corretta nel codice – akrun

+0

Quindi, non posso usare i livelli() in mutato? Ho bisogno di codificare esplicitamente la variabile come un fattore di nuovo? Hmm ... (% <>% dovrebbe essere a posto, pipe e assegna i dati) – user3393472

+0

Sì, voglio mutare x. Pensavo che "livelli (x)" sarebbero stati sufficienti per mutare per capire che voglio mutare x. Immagino che sia una scelta di design, perché funziona in questo modo con "dentro". – user3393472

risposta

22

Io non sono del tutto sicuro di aver capito la tua domanda correttamente, ma se si desidera modificare i livelli del fattore di cyl con mutate() si potrebbe fare:

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

si otterrebbe:

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

Forse stai cercando questa funzione plyr :: revalue:

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

Puoi vedere anche plyr :: mapvalues.

18

Con il nuovo pacchetto forcats di @hadley (announcement sul blog RStudio), anche questo è facile.

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

Forcats è anche parte del tidyverse (announcement), che plyr non è secondo @hadley (vedi il primo commento nell'annuncio).

10

È possibile utilizzare la funzione recode da dplyr.

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

Nota che la ricodifica funziona solo sui vettori, vedi la risposta di PaulFrater per una versione che funziona. – Magnus

7

non posso commentare perché non ho abbastanza punti reputazione, ma ricodificare funziona solo su un vettore, in modo che il codice di cui sopra in @ risposta di Stefano dovrebbe essere

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

Dalla mia comprensione, la risposta attualmente accettata cambia solo l'ordine del fattore livelli, non le effettive etichette (ovvero, come vengono chiamati i livelli del fattore).Per illustrare la differenza tra livelli e etichette, si consideri il seguente esempio:

Girare cyl in fattore (livelli specificando non sarebbero necessari in quanto sono codificati in ordine alfanumerico):

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 

Change l'ordine di livelli (ma non le etichette si: cyl è ancora la stessa colonna)

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 

assegnare nuovi etichette a cyl L'ordine delle etichette sia: c (8, 6, 4), quindi specifichiamo nuove etichette come segue:

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 

Nota come questa colonna differisce rispetto alle nostre prime colonne:

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 

Maggiori dettagli:

se dovessimo cambiare i livelli di cyl usando mtcars2 anziché mtcars3, avremmo bisogno di specificare le etichette in modo diverso per ottenere lo stesso risultato. L'ordine di etichette per mtcars2 era: c (4, 6, 8), quindi specifichiamo nuove etichette come segue

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

differenza mtcars3$cyl e mtcars4$cyl, le etichette di mtcars4$cyl e mtcars5$cyl sono quindi identici, benché i loro livelli hanno un ordine diverso.

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 
Problemi correlati