Perché le dichiarazioni IfElse di R non possono tornare vettori?
-
20-09-2019 - |
Domanda
Ho trovato le dichiarazioni IfElse di R di essere piuttosto utile di tanto in tanto. Ad esempio:
ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2
Ma io sono un po 'confusa dal seguente comportamento.
ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3
Si tratta di una scelta progettuale che è sopra la mia paygrade?
Soluzione
La documentazione per gli stati ifelse
:
ifelse
restituisce un valore con la stessa forma cometest
che viene riempito con elementi selezionati da uno oyes
no
seconda che l'elemento ditest
èTRUE
oFALSE
.
Dal momento che si sta passando valori di prova di lunghezza 1, si stanno ottenendo risultati di lunghezza 1. Se si passa vettori di prova più lunghi, si ottengono risultati più lunghi:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4
Quindi ifelse
è destinato per lo scopo specifico di testare un vettore di booleani e restituendo un vettore della stessa lunghezza, riempita con elementi presi dal (vettore) yes
e argomenti no
.
Si tratta di una confusione comune, a causa del nome della funzione, utilizzare questo, quando in realtà si vuole solo una normale costruzione if () {} else {}
invece.
Altri suggerimenti
Scommetto che si desidera una semplice dichiarazione if
invece di ifelse
- in R, if
non è solo una struttura di controllo del flusso, 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 noti che è possibile aggirare il problema se si assegna il risultato all'interno della 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
sì, penso IfElse () è in realtà progettato per quando si ha un gran lunga vettore di test e si desidera mappare ciascuno per una delle due opzioni. Per esempio, faccio spesso colori per la trama () in questo modo:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Se si ha un gran lunga vettore di test, ma voleva coppie per le uscite, è possibile utilizzare sapply()
o plyr
di llply()
o qualcosa del genere, forse.
Ecco un approccio simile a quello suggerito da Cath, ma può funzionare con i vettori pre-assegnato esistenti
E 'basato su utilizzando il get()
in questo modo:
a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
A volte l'utente ha solo bisogno di una dichiarazione switch
invece di un ifelse
. In tal caso:
condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2
(che è un'altra opzione la sintassi della risposta di Ken Williams)
usare `if`, per esempio
> `if`(T,1:3,2:4)
[1] 1 2 3
Nel tuo caso, utilizzando if_else
da dplyr
sarebbe stato utile: if_else
è più severe rispetto ifelse
, e getta un errore per il vostro caso:
library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2