Search code examples
rcumsum

How to perform cumsum with reset at 0 in R?


I have a table and I want to get the cumulative sum within a group(by ID), but the cumulative count should reset if the counter is 0 at any point within a group and again start the cumulative count from 1.

ID  Counter  Cumulative       
A  1         1
A  0         0              
A  1         1                
A  1         2                
B  1         1                 
B  0         0                
B  1         1    

Solution

  • Create a temporary group column to create a new group everytime you encounter a 0.

    library(dplyr)
    
    df %>%
      group_by(ID, grp = cumsum(Counter == 0)) %>%
      mutate(Cumulative = cumsum(Counter)) %>%
      ungroup() %>%
      select(-grp) -> result
    
    result
    
    #  ID    Counter Cumulative
    #  <chr>   <int>      <int>
    #1 A           1          1
    #2 A           0          0
    #3 A           1          1
    #4 A           1          2
    #5 B           1          1
    #6 B           0          0
    #7 B           1          1
    

    The same logic can be implemented in base R and data.table as :

    df$Cumulative <- with(df, ave(Counter, ID, cumsum(Counter == 0), FUN = cumsum))
    
    library(data.table)
    setDT(df)[, Cumulative := cumsum(Counter), .(ID, cumsum(Counter == 0))]
    

    data

    df <- structure(list(ID = c("A", "A", "A", "A", "B", "B", "B"), Counter = c(1L, 
    0L, 1L, 1L, 1L, 0L, 1L)), class = "data.frame", row.names = c(NA, -7L))