2012-02-25 24 views
9

¿Por qué la construcción if-else y la función ifelse() se comportan de manera diferente?if-else vs ifelse con listas

mylist <- list(list(a=1, b=2), list(x=10, y=20)) 

l1 <- ifelse(sum(sapply(mylist, class) != "list")==0, mylist, list(mylist)) 

l2 <- 
if(sum(sapply(mylist, class) != "list") == 0){ # T: all list elements are lists 
    mylist 
} else { 
    list(mylist) 
} 

all.equal(l1,l2) 
# [1] "Length mismatch: comparison on first 1 components" 

Respuesta

11

if ( cond) { yes } else { no } es una estructura de control. Fue diseñado para efectuar las horquillas de programación en lugar de procesar una secuencia. Creo que muchas personas provienen de SPSS o SAS cuyos autores eligieron "IF" para implementar una asignación condicional dentro de sus funciones DATA o TRANSFORM y por lo tanto esperan que R se comporte igual, mientras que R proviene de una tradición de programación. Los bucles for-implícitos de R están incorporados a las muchas funciones vectorizadas (incluido el ifelse).

ifelse toma una expresión que construye un vector de valores lógicos como primer argumento. El segundo y tercer argumentos deben ser vectores de igual longitud y se elige el primero de ellos o el segundo. Esto es similar a los comandos SPSS/SAS IF que tienen un modo implícito de operación by-row.

12

De la documentación ifelse:

‘ifelse’ returns a value with the same shape as ‘test’ which is 
filled with elements selected from either ‘yes’ or ‘no’ depending 
on whether the element of ‘test’ is ‘TRUE’ or ‘FALSE’. 

Por lo que su entrada tiene una longitud de lo que la salida se trunca a la longitud 1.

También puede ver esto ilustrado con un ejemplo más sencillo:

ifelse(TRUE, c(1, 3), 7) 
# [1] 1 
+1

+1. Me pregunto qué hay detrás de esta decisión de diseño ... – Ryogi

+0

@Dason, en una nota no relacionada, si digo que tengo esto 'df.stats $ Mean.Result2 <- ifelse ((df.stats $ t.test.equal <= 0.05 & df.stats $ f.test> 0.05 & df.stats $ Mean.Diff <0), "Slower", 0) ' ¿Existe alguna forma alternativa de escribirlo usando if - else build? hace que el rendimiento de ifelse venza al de else si construye –