r - How could I speed up the following for loop? -


rm(list = ls()) <- seq(from = 1, = 50000, = 1) b <- seq(from = 1, = 10000, = 2) c <- seq(from = 1, = 10000, = 3)  2 <- rep(na, length(a)) 3 <- rep(na, length(a))  system.time(   (i in seq_along(a))   {     if (length(tail(which(a[i] > b),1)) != 0 & length(tail(which(a[i] > c),1)) != 0)     {           two[i] <- tail(which(a[i] > b),1)       three[i] <- tail(which(a[i] > c),1)     }     else         {           two[i] <- na       three[i] <- na     }   }  ) build_b <- b[two] build_c <- c[three] 

what trying find b , c looked @ time of a. prelocating memory in vectors two , three in attempt save time , can keep track of indexing of occurrences. after loop completed build new vectors according indexing computed. operation takes 10 sec compute. question how can speed operation?

thank you!

here solution using findinterval:

## assume a, b , c sorted 2 <- findinterval(a-1l, b) 3 <- findinterval(a-1l, c)  two[two==0] <- na three[three==0] <- na  build_b <- b[two] build_c <- c[three] 

and here little benchmark:

a <- seq(from = 1, = 50000, = 1) b <- seq(from = 1, = 10000, = 2) c <- seq(from = 1, = 10000, = 3)  pops <- function(a, b, c) {    2 <- rep(na, length(a))   3 <- rep(na, length(a))    (i in seq_along(a))   {     if (length(tail(which(a[i] > b),1)) != 0 & length(tail(which(a[i] > c),1)) != 0)     {           two[i] <- tail(which(a[i] > b),1)       three[i] <- tail(which(a[i] > c),1)     }     else         {           two[i] <- na       three[i] <- na     }   }    return(list(b=b[two], c=c[three])) }  droopy <- function(a, b, c) {    2 <- rep(na, length(a))   3 <- rep(na, length(a))    (i in seq_along(a))   {     if (any(u <- (a[i] > b)) & any(v <- (a[i] > c)))     {           two[i] <- sum(u)       three[i] <- sum(v)     }     else         {           two[i] <- na       three[i] <- na     }   }   return(list(b=b[two], c=c[three])) }  sgibb <- function(a, b, c) {   ## assume a, b , c sorted   2 <- findinterval(a-1l, b)   3 <- findinterval(a-1l, c)    two[two==0] <- na   three[three==0] <- na    return(list(b=b[two], c=c[three])) } 

the benchmark:

library("rbenchmark") benchmark(pops(a, b, c), droopy(a, b, c), sgibb(a, b, c), order="relative", replications=2) #             test replications elapsed relative user.self sys.self user.child sys.child #3  sgibb(a, b, c)            2   0.010      1.0     0.008    0.004          0         0 #2 droopy(a, b, c)            2   8.639    863.9     8.613    0.000          0         0 #1   pops(a, b, c)            2  26.838   2683.8    26.753    0.004          0         0  identical(pops(a, b, c), sgibb(a, b, c)) ## true identical(droopy(a, b, c), sgibb(a, b, c)) ## true 

Comments

Popular posts from this blog

c# - How to get the current UAC mode -

postgresql - Lazarus + Postgres: incomplete startup packet -

javascript - Ajax jqXHR.status==0 fix error -