Per loop in R sono notoriamente lento, ma qui c'è un altro problema. È molto più veloce preallocare i risultati vettore, res, piuttosto aggiungere a res a ogni iterazione.
Di seguito è possibile confrontare la velocità della versione precedente con una versione che inizia semplicemente con un vettore, res, di lunghezza N e modifica l'elemento ith durante il 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
Inoltre, come Sharpie points out, siamo in grado di rendere questo leggermente più veloce utilizzando le funzioni di ricerca, come apply
(o dei suoi parenti, sapply
e 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
fonte
2009-07-23 04:19:53
Cosa c'è di sbagliato nella seconda risposta in tale thread di elenco R: res <- rnorm (10^6) -rnorm (10^6)? – ars
@ars: hai assolutamente ragione - questo fornisce la soluzione più veloce (di un ordine di grandezza). Il miglior consiglio sarebbe 1. Usare le funzioni che funzionano naturalmente sui vettori (come fa rnorm); 2. In caso contrario, utilizzare una funzione * apply; 3. In caso contrario, utilizzare un ciclo for con preallocazione. –