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
Post a Comment