Perché le istruzioni ifelse di R non possono restituire i vettori?

Ho trovato le dichiarazioni ifelse di R per essere abbastanza utile di volta in volta. Per esempio:

ifelse(TRUE,1,2) # [1] 1 ifelse(FALSE,1,2) # [1] 2 

Ma sono un po ‘confuso dal seguente comportamento.

 ifelse(TRUE,c(1,2),c(3,4)) # [1] 1 ifelse(FALSE,c(1,2),c(3,4)) # [1] 3 

Questa è una scelta di design che è al di sopra del mio pagamento?

La documentazione per ifelse afferma:

ifelse restituisce un valore con la stessa forma del test che viene riempito con elementi selezionati da yes o no seconda che l’elemento di test sia TRUE o FALSE .

Poiché stai passando i valori di prova della lunghezza 1, ottieni i risultati della lunghezza 1. Se superi i vettori di prova più lunghi, otterrai risultati più lunghi:

 > ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4)) [1] 1 4 

Quindi ifelse è inteso allo scopo specifico di testare un vettore di booleani e restituire un vettore della stessa lunghezza, pieno di elementi presi dal (vettore) yes e no argomenti.

È una confusione comune, a causa del nome della funzione, usarla quando in realtà si desidera solo una normale costruzione if () {} else {} .

Scommetto che vuoi una semplice istruzione if invece di ifelse – in R, if non è solo una struttura di controllo-stream, può restituire un valore:

 > if(TRUE) c(1,2) else c(3,4) [1] 1 2 > if(FALSE) c(1,2) else c(3,4) [1] 3 4 

si, penso che ifelse () sia davvero progettato per quando hai un lungo vettore di test e vuoi mappare ciascuno a una delle due opzioni. Per esempio, faccio spesso i colors per plot () in questo modo:

 plot(x,y, col = ifelse(x>2, 'red', 'blue')) 

Se avevi un lungo vettore di test ma volevi coppie per le uscite, potresti usare sapply() o plyr ‘s llply() o qualcosa del genere, forse.

Si noti che è ansible aggirare il problema se si assegna il risultato all’interno di ifelse :

 ifelse(TRUE, a <- c(1,2), a <- c(3,4)) a # [1] 1 2 ifelse(FALSE, a <- c(1,2), a <- c(3,4)) a # [1] 3 4 

A volte l’utente ha solo bisogno di un’istruzione switch invece di un ifelse . In quel caso:

 condition <- TRUE switch(2-condition, c(1, 2), c(3, 4)) #### [1] 1 2 

(che è un'altra opzione di syntax della risposta di Ken Williams)

Ecco un approccio simile a quello suggerito da Cath, ma può funzionare con i vettori pre-assegnati esistenti

Si basa sull’utilizzo di get() modo:

 a <- c(1,2) b <- c(3,4) get(ifelse(TRUE, "a", "b")) # [1] 1 2