Pourquoi ne peuvent-IfElse déclarations de R vecteurs retour?
-
20-09-2019 - |
Question
J'ai trouvé des déclarations IfElse de R être assez pratique de temps en temps. Par exemple:
ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2
Mais je suis un 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 qui est au-dessus de mon paygrade?
La solution
La documentation pour les Etats ifelse
:
ifelse
renvoie une valeur ayant le même forme quetest
qui est rempli de éléments choisis parmi une ou l'autre ouyes
no
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, vous obtiendrez des résultats plus:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4
ifelse
est destiné à l'usage spécifique de l'essai d'un vecteur de booléens et retourner un vecteur de la même longueur, rempli d'éléments prélevés sur le (vecteur) yes
et arguments no
.
Il est une confusion commune, à cause du nom de la fonction, à utiliser quand vraiment vous voulez juste une construction if () {} else {}
normale à la place.
Autres conseils
Je parie que vous voulez une simple déclaration de if
au lieu de ifelse
- dans R, if
est non seulement une structure de contrôle de flux, il peut retourner 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 attribuez 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
ouais, je pense ifelse () est vraiment conçu pour quand vous avez un grand long vecteur de tests et que vous voulez cartographier chacun à l'une des deux options. Par exemple, je fais souvent des couleurs pour complot () de cette façon:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Si vous aviez un grand long vecteur de tests mais je voulais paires pour les sorties, vous pouvez utiliser sapply()
ou de plyr
de llply()
ou quelque chose, peut-être.
Voici une approche similaire à celle proposée par Cath, mais il peut fonctionner avec des vecteurs pré-existants affectés
Il est basé sur l'utilisation du 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 déclaration de switch
au lieu d'un ifelse
. Dans ce cas:
condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2
(ce qui est une autre option de syntaxe de la réponse de Ken Williams)
utiliser `if`, par exemple,
> `if`(T,1:3,2:4)
[1] 1 2 3
Dans votre cas, l'utilisation de if_else
dplyr
aurait été utile: if_else
est plus stricte que ifelse
et jette 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