2013-04-26 10 views
6

Ho 2 vettori numerici, uno memorizza i valori per calcolare il massimo da, altre lunghezze di una finestra mobile per calcolare quei massimi su base progressiva. Di seguito è riportato un codice di esempio. Generalmente sto cercando di velocizzare il codice all'interno di system.time. C'è qualche funzione pronta o un modo vettoriale per fare la stessa cosa?Qual è il modo più veloce in R per calcolare rolling max con una dimensione variabile della finestra mobile?

a <- rep(1:5,20000) 
set.seed(123) 
b <- rep(sample(1:50),2000) 

system.time({ 
out <- vector(mode='numeric', length=NROW(a)) 
for(i in seq(a)) { 
    if (i-b[i]>=0) out[i] <- max(a[(i-b[i]+1):i]) 
    else out[i] <- NA 
} 
}) 
+0

+1 Buona domanda. Questo è un problema interessante da provare e ottimizzare! –

risposta

1

Managed vectorize parti di esso:

originale -

system.time({ 
    out <- vector(mode='numeric', length=NROW(a)) 
    for(i in seq(a)) { 
    if (i-b[i]>=0) out[i] <- max(a[(i-b[i]+1):i]) 
    else out[i] <- NA 
    } 
}) 
## user system elapsed 
## 0.64 0.00 0.64 

Leggermente vettorializzare -

system.time({ 
    nr <- NROW(a) 
    out <- rep(NA,nr) 
    m <- 1:nr - b + 1 
    n <- (1:nr)[m>0] 

    for(i in n) 
    out[i] <- max(a[m[i]:i]) 
}) 
## user system elapsed 
## 0.39 0.00 0.39 
+0

Grazie, ora il codice sembra migliore – user1603038

+0

+1 Soluzione piacevole –

0

È possibile vectorise le parti di questo problema, in particolare in cui è necessario per scoprire la posizione dell'indice iniziale in a (l'ho chiamato str) e la fine della finestra (end), ma devo utilizzare un costrutto di ciclo per applicare le posizioni di indice a a per prendere lo max utilizzando mapply. In questo modo:

x <- seq_len(length(a)) 
end <- which(x-b > 0) 
str <- end - b[end] 
res <- a 
res[ - end ] <- NA 
res[end] <- mapply(function(x,y) max(a[ x:y ]) , str , end) 

e il confronto con la 's risposta @ e4e5f4:

identical(res , out) 
[1] TRUE 

Tuttavia non è abbastanza più velocemente:

user system elapsed 
0.46 0.00 0.47 

Se ci fosse un modo per vectorise il l'ultima operazione quindi sarebbe molto veloce, ma non riesco a pensare ad alcun modo per farlo al momento!

Problemi correlati