2015-07-01 12 views
10

Questo dovrebbe essere piuttosto semplice ma anche dopo aver controllato tutta la documentazione e gli esempi in linea, non capisco.Uso dell'interruttore() in R per sostituire i valori vettoriali

Mi piacerebbe usare switch() per sostituire i valori di un vettore di caratteri.

un falso, estremamente semplice, ad esempio riproducibile:

test<-c("He is", "She has", "He has", "She is") 

Diciamo che voglio assegnare "1" per le frasi tra cui il verbo "essere" e "2" per le frasi tra cui il verbo "avere ". Quanto segue non funziona: messaggio

test<-switch(test, 
       "He is"=1, 
       "She is"=1, 
       "He has"=2, 
       "She has"=2) 

Errore:

+ + + + Error in switch(test, `He is` = 1, `She is` = 1, `He has` = 2, `She has` = 2) : 
    EXPR must be a length 1 vector 

penso ESPR è infatti una lunghezza di 1 vettore, quindi cosa c'è di sbagliato?

ho pensato che forse R caratteri come sostituti del previsto, ma né l'interruttore di avvolgimento() in un "as.integer", né i seguenti lavori:

test<-switch(test, 
       "He is"="1", 
       "She is"="1", 
       "He has"="2", 
       "She has"="2") 

Forse non Vectorize, e che dovrei fare una ciclo continuo? È così? Sarebbe deludente, considerando la forza di R la vettorizzazione. Grazie in anticipo!

+2

Vector "test" è di lunghezza 4. Non può funzionare. Vedi con 'test <-" He is "'. –

+5

Stai cercando di raggiungere questo? Codice <- c ("Lui è" = 1, "Lei è" = 1, "Lui ha" = 2, "Lei ha" = 2); codice [Test] '? – ExperimenteR

+1

Wow @ExperimenteR, che è elegante ... Non sapevo che se selezionassi gli oggetti di un vettore numerico con un attributo nomi usando un carattere, R userebbe l'attributo nomi per far corrispondere i numeri del vettore numerico al mio personaggio vettore. Questa è la mia soluzione preferita, ma non posso sceglierla come risposta perché la domanda era come usare switch() correttamente. Thumbs up tho – torwart

risposta

7

La forma Vectorised di if è ifelse:

test <- ifelse(test == "He is", 1, 
     ifelse(test == "She is", 1, 
     ifelse(test == "He has", 2, 
     2))) 

o

test <- ifelse(test %in% c("He is", "She is"), 1, 2) 

switch è fondamentalmente un modo di scrivere annidate if - else test. Si dovrebbe pensare a if e switch come al flusso di controllo, non come operatori di trasformazione dati. Li usi per controllare l'esecuzione di un algoritmo, ad esempio per verificare la convergenza o per scegliere quale percorso di esecuzione prendere. Non li useresti per manipolare direttamente i dati nella maggior parte delle circostanze.

8

È coud tenta

test_out <- sapply(1:length(test), function(x) switch(test[x], 
      "He is"=1, 
      "She is"=1, 
      "He has"=2, 
      "She has"=2)) 

o equivalentemente

test_out <- sapply(test, switch, 
      "He is"=1, 
      "She is"=1, 
      "He has"=2, 
      "She has"=2) 
+1

Questa sembra essere la soluzione, grazie, in realtà in una forma ancora più semplice in cui "test" è l'oggetto di sapply – torwart

+1

Scusa, un'altra risposta ha incluso una spiegazione ampia delle nozioni dietro il problema. Ma prometto che ti revocherò non appena la mia reputazione lo consentirà tra qualche settimana. – torwart

-1

magari provare questo:

test<-c("He is", "She has", "He has", "She is") 
numbers <-c(1,2,2,1) 
test<-mapply(switch, as.list(test), as.list(numbers)) 
+0

In questo modo stai facendo la versione vettoriale di 'test <- switch (test, numeri)'. 'numbers' è qui come parametro' else'. È come scrivere 'test <- numeri'. Questo non controlla nemmeno il valore in 'test'. Hai già la risposta in "numeri". – Gedrox

11

Ecco il modo corretto di vectorize una funzione, ad es. interruttore:

# Data vector: 
test<-c("He is", "She has", "He has", "She is") 

# Vectorized SWITCH: 
foo <- Vectorize(function(a) { 
    switch(as.character(a), 
         "He is" = 1, 
         "She is" = 1, 
         "He has" = 2, 
         2) 

}, "a") 

# Result: 
foo(test) 

    He is She has He has She is 
     1  2  2  1 

Spero che questo aiuta.

1

"Vectorize" si basa sulla funzione "mapply", mentre "ifelse" è una funzione di base che deve essere già vettorizzata. Quindi in termini di prestazioni "Vectorize" potrebbe essere più lento. È facile da vettorizzare una funzione R con la famiglia "apply", ma le prestazioni di solito sono un problema su grandi volumi. Meglio utilizzare le funzioni di base ottimizzate per lavorare con i vettori.

0

Ho trovato questo approccio il più leggibile:

# input 
test <-c("He is", "She has", "He has", "She is", "Unknown", "She is") 

# mapping 
map <- c(
    "He is" = 1, 
    "She has" = 2, 
    "He has" = 2, 
    "She is" = 1) 

answer <- map[test] 

# output 
answer 
He is She has He has She is <NA> She is 
    1  2  2  1  NA  1 

Se test è numerico, deve convertire il valore di character per utilizzare questo.

Problemi correlati