2012-01-12 13 views
6

Mientras R ifelse es increíblemente útil, tiene un defecto en particular: en la llamada ifelse(test, yes, no) se evalúan todos los elementos de yes y no, incluso aquellos que se desecha.Buscando un ifelse más eficiente()

Esto es más bien un desperdicio si se está usando en el medio de un ejercicio numérico complicado, dicen en una función que se alimenta a integrate, uniroot, optim o lo que sea. Por ejemplo, uno podría haber

ifelse(test, f(x, y, z), g(a, b, c)) 

donde f y g son arbitrariamente funciones complejas o lentos, posiblemente con la participación más anidados ifelse 's.

¿Alguien ha escrito un reemplazo para ifelse que solo evalúa los elementos de yes/no que se conservarán? Básicamente, algo en la línea de

out <- test 
for(i in seq_along(out)) 
{ 
    if(test[i]) out[i] <- f(x[i], y[i], z[i]) 
    else out[i] <- g(a[i], b[i], c[i]) 
} 

pero sin la torpeza/ineficacia de un bucle explícito. ¿Esto es posible incluso sin entrar en las entrañas de R?

+1

Supongo que * podría * usar el bucle explícito, pero luego creo que seguiré el viejo dicho de que un programador determinado puede escribir Fortran en cualquier idioma ... –

+1

¿qué le parece usar apply? entonces el ifelse() se evalúa para cada elemento, y del mismo modo el 'sí' y 'no solo se evalúan para los elementos relevantes, a menos que mi comprensión de la aplicación sea incorrecta, pero estoy seguro de que me funcionó en el pasado – nzcoops

+0

I intenté usar 'mapply' con if() - else, y eso fue 10 veces más lento que el vectorizado' ifelse'! –

Respuesta

6

No creo que el problema sea ifelse. f y g solo se evalúan una vez en su expresión. Creo que su problema es que f y g son lentos con los vectores.

Puede cambiar las llamadas a f y g para que solo se evalúen en un subconjunto del vector.

out <- numeric(length(test)) #or whatever the output type is 
out[test] <- f(x[test], y[test], z[test]) 
out[!test] <- g(x[!test], y[!test], z[!test]) 

Tendrá que ajustar si cualquier elemento de test son NA.

+0

Sí, he hecho esto también, pero es bastante engorroso. –

+4

Si 'f' y' g' están vectorizados, esta es su mejor opción. Si no, cualquier tipo de ciclo funcionará. Y si crees que es un código feo (que es lo suficientemente justo), puedes envolverlo en una función y esconderlo en un archivo que no miras muy a menudo. –

Cuestiones relacionadas