¿Por qué no pueden IfElse declaraciones de retorno R vectores?
-
20-09-2019 - |
Pregunta
He encontrado declaraciones IfElse de R a ser bastante útil de vez en cuando. Por ejemplo:
ifelse(TRUE,1,2)
# [1] 1
ifelse(FALSE,1,2)
# [1] 2
Pero estoy un poco confundido por el comportamiento siguiente.
ifelse(TRUE,c(1,2),c(3,4))
# [1] 1
ifelse(FALSE,c(1,2),c(3,4))
# [1] 3
¿Es esta una opción de diseño que está por encima de mi paygrade?
Solución
La documentación de los estados ifelse
:
ifelse
devuelve un valor con el mismo forma comotest
que se llena con elementos seleccionados de cualquierayes
ono
dependiendo de si el elemento detest
esTRUE
oFALSE
.
Desde que está pasando valores de la prueba de longitud 1, que está recibiendo resultados de longitud 1. Si pasa vectores de prueba más largos, obtendrá resultados más largos:
> ifelse(c(TRUE, FALSE), c(1, 2), c(3, 4))
[1] 1 4
Así ifelse
está destinado para el propósito específico de la prueba de un vector de booleanos y devolver un vector de la misma longitud, lleno de elementos tomados de la (vector) yes
y argumentos no
.
Es una confusión común, porque del nombre de la función, para utilizar esta opción cuando en realidad sólo desea una construcción normal de if () {} else {}
lugar.
Otros consejos
apuesto desea una declaración if
sencilla en lugar de ifelse
- en R, if
no es sólo una estructura de flujo de control, se puede devolver un valor:
> if(TRUE) c(1,2) else c(3,4)
[1] 1 2
> if(FALSE) c(1,2) else c(3,4)
[1] 3 4
Tenga en cuenta que se puede evitar el problema si se asigna el resultado dentro de la 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í, creo que ifelse () es realmente diseñado para cuando usted tiene una larga grande del vector de pruebas y desea asignar cada uno a una de las dos opciones. Por ejemplo, a menudo hago colores de trama () de esta manera:
plot(x,y, col = ifelse(x>2, 'red', 'blue'))
Si tuviera una larga grande del vector de pruebas, pero quería pares de salidas, se puede usar sapply()
o plyr
de llply()
o algo, tal vez.
Este es un enfoque similar a la sugerida por Cath, pero puede trabajar con vectores asignados previamente existentes
Se basa en el uso de la get()
este modo:
a <- c(1,2)
b <- c(3,4)
get(ifelse(TRUE, "a", "b"))
# [1] 1 2
A veces, el usuario sólo necesita una declaración switch
en lugar de un ifelse
. En ese caso:
condition <- TRUE
switch(2-condition, c(1, 2), c(3, 4))
#### [1] 1 2
(que es otra opción de la sintaxis de la respuesta de Ken Williams)
usar `if`, por ejemplo
> `if`(T,1:3,2:4)
[1] 1 2 3
En su caso, el uso de if_else
dplyr
habría sido útil: if_else
es más estricta que ifelse
, y arroja un error para su caso:
library(dplyr)
if_else(TRUE,c(1,2),c(3,4))
#> `true` must be length 1 (length of `condition`), not 2