J'ai trouvé les instructions ifelse de R de temps en temps assez pratiques. Par exemple:
ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2
Mais je suis quelque peu confus par le comportement suivant.
ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3
Est-ce un choix de conception supérieur à mon niveau de rémunération?
La documentation de ifelse
indique:
ifelse
renvoie une valeur de la même forme quetest
qui est remplie d'éléments sélectionnés parmiyes
ouno
selon que l'élément detest
estTRUE
ouFALSE
.
Puisque vous passez des valeurs de test de longueur 1, vous obtenez des résultats de longueur 1. Si vous passez des vecteurs de test plus longs, vous obtiendrez des résultats plus longs:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4
Ainsi, ifelse
est destiné à des fins spécifiques de test d'un vecteur de booléens et de retour d'un vecteur de même longueur, rempli d'éléments tirés du (vecteur) yes
et no
arguments.
C'est une confusion courante, à cause du nom de la fonction, de l'utiliser quand vraiment vous voulez juste une construction normale de if () {} else {}
à la place.
Je parie que vous voulez une simple instruction if
au lieu de ifelse
- dans R, if
n'est pas seulement une structure de flux de contrôle, elle peut renvoyer une valeur:
> if(TRUE) c(1,2) else c(3,4)
[1] 1 2
> if(FALSE) c(1,2) else c(3,4)
[1] 3 4
Notez que vous pouvez contourner le problème si vous affectez le résultat à l'intérieur du 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
oui, je pense que ifelse () est vraiment conçu pour quand vous avez un grand vecteur de tests et que vous voulez mapper chacune à l'une des deux options. Par exemple, je fais souvent des couleurs pour plot () de cette façon:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Si vous aviez un grand vecteur de tests mais que vous vouliez des paires pour les sorties, vous pourriez utiliser sapply()
ou plyr
llply()
ou quelque chose, peut-être.
Voici une approche similaire à celle suggérée par Cath, mais elle peut fonctionner avec des vecteurs pré-assignés existants
Il est basé sur l'utilisation de la get()
comme ceci:
a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
Parfois, l'utilisateur a juste besoin d'une instruction switch
au lieu d'une ifelse
. Dans ce cas:
condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2
(qui est une autre option de syntaxe de la réponse de Ken Williams)
utilisez `if`, par ex.
> `if`(T,1:3,2:4)
[1] 1 2 3
Dans votre cas, en utilisant if_else
de dplyr
aurait été utile: if_else
est plus strict que ifelse
et génère une erreur pour votre cas:
library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2