Search code examples
rsplitcut

Split a vector and summing values


I'm a R newbie. I've got a vector

vec <- c(105,29,41,70,77,0,56,49,63,0,105)

and i would like to sum values till "0" occurs and then create a vector with such values, such as:

vec2 <- c(322,168,105)

But i really don't know where to start! Any suggestion?


Solution

  • Starting with this vector...

    > vec
     [1] 105  29  41  70  77   0  56  49  63   0 105
    

    We can compute a logical TRUE/FALSE vector of where the zeroes are:

    > vec == 0
     [1] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE
    

    When you add FALSE and TRUE, FALSE is zero and TRUE is one, so if we add that vector up every time we get to a TRUE the value increases. So using cumsum for the cumulative sum, we get:

    > cumsum(vec==0)
     [1] 0 0 0 0 0 1 1 1 1 2 2
    

    Now that result defines the groups that we want to add up within, so let's split vec by that result:

    > split(vec, cumsum(vec==0))
    $`0`
    [1] 105  29  41  70  77
    
    $`1`
    [1]  0 56 49 63
    
    $`2`
    [1]   0 105
    

    So apart from the zeroes in the second and subsequent parts of the list, that's the numbers we want to add up. Because we are adding we can add the zeroes and it doesn't make any difference (but if you wanted the mean you would have to drop the zeroes). Now we use sapply to iterate over list elements and compute the sum:

    > sapply(split(vec, cumsum(vec==0)),sum)
      0   1   2 
    322 168 105 
    

    Job done. Ignore the 0 1 2 labels.