[R] avoiding a loop

Ray Brownrigg Ray.Brownrigg at mcs.vuw.ac.nz
Fri Oct 27 05:17:28 CEST 2006


On Wednesday 25 October 2006 07:36, Leeds, Mark (IED) wrote:
> I think I asked a similar question 3 years ago to the  Splus list and I
> think the answer was no or noone answered so noone should spend more
> than 5 minutes on this
> because it could definitely be a waste of time.
>
> My question is whether the function below can be rewritten without a for
> loop. apply is fine if it can be done that way but i doubt it. I call it
> a lot and would
> prefer to not loop.
>
> #-----------------------------------------------------------------------
> --------------------------
>
> constructLt<-function(invector) {
>
> outvector<-invector
>
>  for ( i in 2:length(invector) ) {
>  if ( invector[i] < 1 ) {
>   outvector[i]<-invector[i]*outvector[i-1]
>  }
> }
>
> return(outvector)
>
> }
>
Depending on the nature of your data, there is a faster way.  It still 
involves looping, but not over the entire vector.

Try the following:
constructLt <- function(invector) {
  outvector <- invector
  cs <- cumsum(rle(invector < 1)$lengths)
  if (invector[1] < 1)
    cs <- c(1, cs)
  for (i in 0:(length(cs)%/%2 - 1)){
    starti <- cs[2*i + 1]
    stopi <- cs[starti + 1]
    outvector[starti:stopi] <- cumprod(invector[starti:stopi])
  }
  return(outvector)
}

It is in the order of 3 times as fast for random vectors of considerable 
length (> 1000).  For random vectors of length 50 it is about the same speed 
as the full looping algorithm.  However if the data is such that there are 
longer runs (than N(1, 1)), then you might expect a better speedup.

HTH
Ray Brownrigg



More information about the R-help mailing list