¿Por qué las declaraciones ifelse de R no pueden devolver vectores?

He encontrado que las declaraciones de ifelse de R son bastante útiles de vez en cuando. Por ejemplo:

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

Pero estoy algo confundido por el siguiente comportamiento.

 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?

La documentación para estados ifelse :

ifelse devuelve un valor con la misma forma que la test que se llena con elementos seleccionados de yes o no según si el elemento de la test es TRUE o FALSE .

Dado que está pasando valores de prueba de longitud 1, obtendrá 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í que ifelse está destinado al propósito específico de probar un vector de booleanos y devolver un vector de la misma longitud, lleno de elementos tomados del (vector) yes y no argumentos.

Es una confusión común, debido al nombre de la función, utilizar esto cuando en realidad solo desea una construcción if () {} else {} normal.

Apuesto a que quieres una statement if simple en lugar de ifelse : en R, if no es solo una estructura de flujo de control, 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 

Sí, creo que ifelse () está diseñado para cuando tienes un gran vector largo de pruebas y deseas asignar cada una a una de dos opciones. Por ejemplo, a menudo hago colores para plot () de esta manera:

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

Si tuviera un gran vector largo de pruebas pero deseara pares para las salidas, podría usar sapply() o plyrllply() o algo así, tal vez.

Tenga en cuenta que puede eludir el problema si asigna el resultado dentro de 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 veces, el usuario solo necesita una instrucción switch lugar de ifelse . En ese caso:

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

(que es otra opción de syntax de la respuesta de Ken Williams)

Este es un enfoque similar al sugerido por Cath, pero puede funcionar con vectores preasignados existentes

Se basa en usar el get() así:

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