[R] How do I avoid a loop?

Gabor Grothendieck ggrothendieck at gmail.com
Tue Jun 19 16:44:12 CEST 2007


Here is a slight variation.  The second line is unchanged from my
prior solution but the first line is different.  The previous one I posted
was slightly more complex and took about 50% longer to run than
this one:

   xx <- (cumsum(!x) + 1) * x
   (seq_along(x) - match(xx, xx) + 1) * x

> # performance testing
>
> f1 <- function(x) {
+ xx <- cumsum(diff(c(FALSE, x)) > 0)
+ (seq_along(x) - match(xx, xx) + 1) * x
+ }
>
> f2 <- function(x) {
+    xx <- (cumsum(!x) + 1) * x
+    (seq_along(x) - match(xx, xx) + 1) * x
+ }
>
>
> f3 <- function(x) {
+ j <- 0
+ for(i in seq_along(x)) x[i] <- if (x[i]) j <- j+1 else j <- 0
+ x
+ }
>
> set.seed(1)
> x <- sample(c(TRUE, FALSE), 100000, replace = TRUE)
> system.time(out1 <- f1(x))
   user  system elapsed
   0.10    0.02    0.12
> system.time(out2 <- f2(x))
   user  system elapsed
   0.07    0.01    0.08
> system.time(out3 <- f3(x))
   user  system elapsed
   1.65    0.00    1.72
> identical(out1, out2)
[1] TRUE
> identical(out1, out3)
[1] TRUE


On 6/19/07, Gabor Grothendieck <ggrothendieck at gmail.com> wrote:
> xx is 1 in every position of the first run of TRUE, 2 in every
> position in the 2nd run of TRUE and so on.  The parenthesized
> expression in the second line converts those to increasing
> values and multiplying it by x zaps the garbage in the positions
> that correspond to FALSE in x.
>
> xx <- cumsum(diff(c(FALSE, x)) > 0)
> (seq_along(x) - match(xx, xx) + 1) * x
>
>
> On 6/19/07, Feng, Ken <ken.feng at citi.com> wrote:
> > Hi,
> >
> > I start with an array of booleans:
> >
> >        x <- c( TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE );
> >
> > I want to define an y <- f(x) such that:
> >
> >        y <- c( 1, 2, 3, 0, 0, 1, 2, 0, 1 );
> >
> > In other words, do a cumsum when I see a TRUE, but reset to 0 if I see a FALSE.
> >
> > I know I can do this with a very slow and ugly loop or maybe use apply,
> > but I was hoping there are some R experts out there who can show me
> > a cleaner/more elegant solution?
> >
> > Thanks in advance.
> >
> > - Ken
> >
> > ______________________________________________
> > R-help at stat.math.ethz.ch mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-help
> > PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
> > and provide commented, minimal, self-contained, reproducible code.
> >
>



More information about the R-help mailing list