Search code examples
rcumsumrollapply

Conditional extract from vector using rollapply


I am trying to extract a series of values in a vector that meet a certain condition. To illustrate this imagine I have the following vector:

a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)

I would like to isolate consecutive values that whose sum is less than 10 so that the output looks like this:

[1] 1 2 1 3
[1] 3 2
[1] 1 1 1 1 4
[1] 5

I can solve this very inefficiently by using zoo::rollsum() and a logical test

which(rollsum(a,2) < 10)

but in order to do so I have to run it several times, each time increasing the rolling window. Again I can do this in a loop but it's clearly not the best way.

Can anyone think of a solution for this? Any help would be much appreciated!


Solution

  • I would use my own loop. The result is the same as Maurits':

    a <- c(1,2,1,3,12,3,2,15,1,1,1,1,4,5,20)
    
    my.roll <- function(x, limit) {
      res <- vector("list", length(x))
      ctr <- 1
      for (i in seq_along(x)) {
        res[[ctr]] <- c(res[[ctr]], x[i])
        if (sum(res[[ctr]], x[i+1], na.rm = TRUE) > limit) {ctr = ctr+1} else {ctr}
      }
      res <- res[!sapply(res, is.null) & sapply(res, function(x) sum(x) <= limit)]
      return(res)
    }
    my.roll(a, 10)