2013-04-26 12 views
6

Mam 2 wektory numeryczne, jeden przechowuje wartości, aby obliczyć maksimum, kolejne długości okna przewijania, aby obliczyć te maksima w sposób ciągły. Poniżej znajduje się przykładowy kod. Ogólnie próbuję przyspieszyć kod wewnątrz system.time. Czy jest jakaś gotowa funkcja lub wektoryzowany sposób na zrobienie tego samego?Jaka jest najszybsza droga w R do obliczenia toczenia maksymalnego przy zmiennym rozmiarze okna toczenia?

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 Dobre pytanie. To jest interesujący problem, aby spróbować i zoptymalizować! –

Odpowiedz

1

Udało się wektorować części z nich:

Original -

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 

Lekko wektorowy -

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

Dzięki, teraz kod wygląda lepiej – user1603038

+0

+1 Ładne rozwiązanie –

0

Można vectorise części tego problemu, zwłaszcza tam, gdzie trzeba aby znaleźć wyjściową pozycję indeksu w a (nazwałem to str) i koniec okna (end), ale muszę użyć konstrukcji pętli, aby zastosować te pozycje indeksu do a, aby pobrać max przy użyciu mapply. Tak:

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) 

i porównując z @ „s e4e5f4 odpowiedź:

identical(res , out) 
[1] TRUE 

Jednak to nie dość tak szybko:

user system elapsed 
0.46 0.00 0.47 

Jeżeli istnieje sposób, aby vectorise ostatnia operacja, to byłoby naprawdę szybko, ale nie mogę wymyślić żadnego sposobu, aby to zrobić w tej chwili!

Powiązane problemy