4

This is similar to previous post for cumulative sum that resets based on value in another column except that I want to restrict the sum so that it also resets when it reaches a maximum value. For example, if the maximum value is 3:

> data.frame(x=rep(1,10), 
+ y=c(0,0,1,0,0,0,0,1,0,0), 
+ cum_sum_mod=c(1, 2, 1, 2, 3, 1, 2, 1, 2, 3))

   x y cum_sum_mod
1  1 0           1
2  1 0           2
3  1 1           1
4  1 0           2
5  1 0           3
6  1 0           1
7  1 0           2
8  1 1           1
9  1 0           2
10 1 0           3

The cum_sum_mod sums the x column until it reaches the max value (3) or the value in y column is 1. I want to avoid using a loop.

Vlad
  • 3,058
  • 4
  • 25
  • 53

2 Answers2

5

By using dplyr

 library(dplyr)

 dat=data.frame(x=rep(1,10), 
             y=c(0,0,1,0,0,0,0,1,0,0))
 dat$B=cumsum(dat$y)
 dat%>%group_by(B)%>%mutate(cum_sum_mod=ifelse(cumsum(x)%%3==0,3,cumsum(x)%%3))

# A tibble: 10 x 4
# Groups:   B [3]
       x     y     B cum_sum_mod
   <dbl> <dbl> <dbl>       <dbl>
 1     1     0     0           1
 2     1     0     0           2
 3     1     1     1           1
 4     1     0     1           2
 5     1     0     1           3
 6     1     0     1           1
 7     1     0     1           2
 8     1     1     2           1
 9     1     0     2           2
10     1     0     2           3
Frank
  • 66,179
  • 8
  • 96
  • 180
BENY
  • 317,841
  • 20
  • 164
  • 234
3

Base R

ave(df$x, cumsum(df$y == 1), FUN = function(x){
    temp = cumsum(x)
    replace(temp, temp > 3, rep(1:3, length.out = sum(temp > 3)))
})
# [1] 1 2 1 2 3 1 2 1 2 3
d.b
  • 32,245
  • 6
  • 36
  • 77