Problema
Tenemos el siguiente data frame.
x y
[1,] -1 99
[2,] 5 4
[3,] 10 -2
[4,] 600 0
[5,] -16 1
[6,] 0 55
Y deseamos obtener un vector fruto de la siguiente comparación de x e y:
1. El menor valor en y si tanto x e y son positivos.
2. Cualquier valor positivo de y si x es negativo.
3. O dejar el valor de x si no se cumplen las dos condiciones anteriores.
Datos
dat <- structure(list(x = c(-1L, 5L, 10L, 600L, -16L, 0L), y = c(99L,
4L, -2L, 0L, 1L, 55L)), .Names = c("x", "y"), class = "data.frame", row.names = c("[1,]",
"[2,]", "[3,]", "[4,]", "[5,]", "[6,]"))
Soluciones
# Extraemos los vectores
x <- dat[, 1]
y <- dat[, 2]
El problema de esta opción es que no es muy eficiente computacionalmente.
ifelse(y >= 0, ifelse(x < 0, y, ifelse(x > y, y, x)), x)
[1] 99 4 10 0 1 0
Esta opción es entre 5 y 6 veces más rápida.
xz[(x < y & x >= 0)| y < 0] <- x[(x < y & x >= 0)| y < 0];z
[1] 99 4 10 0 1 0
Aún más rápida que la anterior.
x * ((x < y & x >= 0) | y < 0) + y * ((x > y & y >= 0) | x < 0)
[1] 99 4 10 0 1 0
Comparativa
Empleamos el paquete microbenchmark para comparar el tiempo de ejecución de las 3 opciones.
microbenchmark(
if_else = ifelse(y >= 0, ifelse(x < 0, y, ifelse(x > y, y, x)), x),
indexar= z[(x < y & x >= 0)| y < 0] <- x[(x < y & x >= 0)| y < 0],
sinindexar = x *((x < y & x >= 0)| y < 0)+ y * ((x > y & y >= 0)| x < 0),
)
Unit: microseconds
expr min lq mean median uq max neval cld
if_else 43.023 47.1785 53.29921 53.289 53.290 107.067 100 b
indexar 8.800 9.2900 10.71218 9.778 10.267 53.290 100 a
sinindexar 7.333 7.8230 8.89833 8.311 8.800 52.800 100 a
La opción ifelse es la menos eficiente. La opción indexar mejora sustancialmente la velocidad de ejecución. Finalmente, la opción sinindexar es algo más rápida aún que indexar. Existen opciones más rápidas incluso, que puedes ver en el enlace del apartado referencias. Sin embargo, quizá la ganancia en velocidad de ejecución no compensa la pérdida de legibilidad.
Entradas relacionadas
- Comparar dos vectores en R: elementos comunes y únicos
- Cómo comparar dos data frames en R
- Comparar el tiempo de ejecución de expresiones en R con microbenchmark
Referencias
No hay comentarios:
Publicar un comentario