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
This should do it for you:> x <- c( TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE ); > y <- rle(x) > unlist(lapply(seq(length(y$lengths)), function(.indx){+ if (y$values[.indx]) seq(y$lengths[.indx]) + else rep(0, y$lengths[.indx]) + })) [1] 1 2 3 0 0 1 2 0 1 On 6/19/07, Feng, Ken <ken.feng@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@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. >-- Jim Holtman Cincinnati, OH +1 513 646 9390 What is the problem you are trying to solve? [[alternative HTML version deleted]]
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. >
One more variation on the solution, no idea how it compares in speed. Using your x ... > ifelse(x, unlist(mapply(seq, to = rle(x)$lengths, from = 1)), 0) [1] 1 2 3 0 0 1 2 0 1 Feng, Ken 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.
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. > > >
Seemingly Similar Threads
- binary symmetric matrix combination
- [PATCH 3/6] Input: Update vmmouse.c to use the common VMW_PORT macros
- [PATCH 3/6] Input: Update vmmouse.c to use the common VMW_PORT macros
- matrix values linked to vector index
- [PATCH 3/6] Input: Update vmmouse.c to use the common VMW_PORT macros