-2

I have the following data table:

enter image description here`

I want to make a cumulative product for the sequences between the zero's, such that i get the following:

enter image description here

I need to do this for several large dataset, and fail to find a efficient way of calculating this. I hope someone is able to help, and thanks in advance.

Jaap
  • 81,064
  • 34
  • 182
  • 193
Rasmus
  • 43
  • 3
  • Do not post your data as an image, please learn how to give a [reproducible example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/5963610) – Jaap Feb 23 '18 at 15:57
  • 2
    You can probably use `?cumprod` for the cumulative product and `?data.table::rleid` to group by zeros. – talat Feb 23 '18 at 15:58

2 Answers2

3
> y=rle(!!x)
> y$values=1:length(y$values)
> ave(x,inverse.rle(y),FUN = cumprod)
 [1]    0    0    3    3    9   36  180 1080    0    0    3   15  105

Write a function and apply it to your data.frame:

f=function(x){
  y=rle(!!x)#(x!=0)
  y$values=1:length(y$values)
  ave(x,inverse.rle(y),FUN = cumprod)
}

rapply(df1,f,"numeric",how="replace")
   V1   V2
1   0    0
2   1    0
3   3    3
4   6    3
5   0    9
6   0   36
7   5  180
8   5 1080
9  10    0
10  0    0
Onyambu
  • 67,392
  • 3
  • 24
  • 53
2

Here is an option using rle and cumprod. We loop through the columns of the dataset with lapply, create a grouping column with rle and then with ave get the cumulative product (cumprod)

df1[] <- lapply(df1, function(x) {
           r1 <- rle(x!=0)
           ave(x, rep(seq_along(r1$values), r1$lengths), FUN = cumprod) 
         })
df1
#   V1   V2
#1   0    0
#2   1    0
#3   3    3
#4   6    3
#5   0    9
#6   0   36
#7   5  180
#8   5 1080
#9  10    0
#10  0    0

data

df1 <- data.frame(V1 = c(0, 1, 3, 2, 0, 0, 5, 1, 2, 0),
     V2 = c(0, 0, 3, 1, 3, 4, 5, 6, 0, 0))
akrun
  • 874,273
  • 37
  • 540
  • 662