Para bucles en R son notoriamente lentos, pero aquí hay otro problema. Es mucho más rápido preasignar el vector de resultados, res, en lugar de anexar res en cada iteración.
A continuación podemos comparar la velocidad de la versión anterior con una versión que simplemente comienza con un vector, res, de longitud N y cambia el elemento ith durante el ciclo.
fn1 <- function(N) {
res <- c()
for (i in 1:N) {
x <- rnorm(2)
res <- c(res,x[2]-x[1])
}
res
}
fn2 <- function(N) {
res <- rep(0,N)
for (i in 1:N) {
x <- rnorm(2)
res[i] <- x[2]-x[1]
}
res
}
> N <- 50000
> system.time(res1 <- fn1(N))
user system elapsed
6.568 0.256 6.826
> system.time(res2 <- fn2(N))
user system elapsed
0.452 0.004 0.496
También, como Sharpie points out, podemos hacer de este un poco más rápido mediante el uso de funciones como R apply
(o sus parientes, y sapply
lapply
).
fn3 <- function(N) {
sapply(1:N, function(i){ x <- rnorm(2); return(x[2] - x[1]) })
}
> system.time(res3 <- fn3(N))
user system elapsed
0.397 0.004 0.397
¿Qué hay de malo con la segunda respuesta en ese hilo de la lista R: res <- rnorm (10^6) -rnorm (10^6)? – ars
@ars: Tiene toda la razón: ofrece la solución más rápida (en un orden de magnitud). El mejor consejo sería 1. Use funciones que funcionan naturalmente en vectores (como rnorm hace); 2. Si eso falla, use una función * apply; 3. Si eso falla, use un ciclo for con preasignación. –