2015-03-18 11 views
5

Ecco un esempio banale di quello che sto cercando di fare:modo idiomatico di combinare livelli di un fattore categorica

iris %>% 
    mutate(Species2 = ifelse(Species %in% c("setosa", "virginica"), "other", as.character(Species)) %>% as.factor) %>% 
    str 
# 'data.frame': 150 obs. of 6 variables: 
# $ Sepal.Length: num 5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ... 
# $ Sepal.Width : num 3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ... 
# $ Petal.Length: num 1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ... 
# $ Petal.Width : num 0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ... 
# $ Species  : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ... 
# $ Species2 : Factor w/ 2 levels "Other","versicolor": 1 1 1 1 1 1 1 1 1 1 ... 

Tuttavia, se voglio fare molteplici unioni, sarei andato a finire con la nidificazione ifelse dichiarazioni, che sto cercando di evitare. Qual è il modo più elegante per farlo? Preferibilmente posso incorporare la soluzione in una pipeline dplyr.

+1

La base sarebbe quella di modificare i livelli dopo aver controllato i 'livelli (iris $ Specie)', ossia i livelli di '(iris $ specie) <- c ('altro', 'versicolor', 'altro') ' – akrun

+2

quindi dopo qualche ricerca in più' plyr :: revalue' sembra andare bene, ma se sto combinando molti livelli in uno c'è un po 'di digitazione ridondante, quindi io vado a indagare su un wrapper che prende una lista con nome ... – kevinykuo

+2

Penso che dovresti mettere le tue regole di classificazione in un data.frame, 'data.frame (Species = c (" setosa "," virginica ") , Species2 = "other") 'e uniscilo dentro. Hai menzionato" multiple merges ", quindi forse questo è già quello che intendevi ... – Frank

risposta

1

È possibile utilizzare match:

species.keep <- c("setosa", "virginica", "other") 
iris %>% mutate(Species2 = species.keep[match(Species, species.keep, nomatch=3)]) 

Usiamo l'argomento nomatch-match per mappare "other" all'ultima posizione del nostro species.keep vettore per tutte le specie che non sono in posizioni precedenti. Nota questo presuppone che "other" non è una specie valida. Dovrai aggiungere lo as.factor ecc., Ma questo dovrebbe arrivare a ciò che desideri. match è la funzione di mappatura della linea di base in R.

0

Se è necessario popolare la matrice iniziale con le corrispondenze possibili, probabilmente sarà necessario utilizzare qualcosa come sapply. Quindi è possibile utilizzare tale array per popolare Species2: metodo R

s <- sapply(levels(iris$Species), 
      function(x) { 
         if (x %in% c("setosa", "virginica")) 
          x = "Other" 
         else 
          x = x 
         }, 
      simplify = F) 

iris %>% 
    mutate(Species2 = (as.character(s[Species])) %>% as.factor) %>% 
    str 
Problemi correlati