Rolling sums for groups with uneven time gaps

前端 未结 6 1387
说谎
说谎 2021-02-16 00:19

Here\'s the tweak to my previously posted question. Here\'s my data:

set.seed(3737)
DF2 = data.frame(user_id = c(rep(27, 7), rep(11, 7)),
            date = as.D         


        
6条回答
  •  青春惊慌失措
    2021-02-16 00:27

    Here are some approaches using zoo.

    1) Define a function sum_last that given a zoo object takes the sum of the values whose times are within k days of the last day in the series and define a roll function which applies it to an entire series. Then use ave to apply roll to each user_id once for k=7 and once for k=14.

    Note that this makes use of the coredata argument to rollapply that was introduced in the most recent version of zoo so be sure you don't have an earlier version.

    library(zoo)
    
    # compute sum of values within k time units of last time point
    sum_last <- function(z, k) {
      tt <- time(z)
      sum(z[tt > tail(tt, 1) - k])
    }
    
    # given indexes ix run rollapplyr on read.zoo(DF2[ix, -1])
    roll <- function(ix, k) {
     rollapplyr(read.zoo(DF2[ix, -1]), k, sum_last, coredata = FALSE, partial = TRUE, k = k)
    }
    
    nr <- nrow(DF2)
    transform(DF2, 
      v_minus7 = ave(1:nr, user_id, FUN = function(x) roll(x, 7)),
      v_minus14 = ave(1:nr, user_id, FUN = function(x) roll(x, 14)))
    

    2) An alternative would be to replace roll with the version shown below. This converts DF2[ix, -1] to "zoo" and merges it with a zero width grid with filled-in gaps. Then rollapply is applied to that and we use window to subset it back to the original times.

    roll <- function(ix, k) {
       z <- read.zoo(DF2[ix, -1])
       g <- zoo(, seq(start(z), end(z), "day"))
       m <- merge(z, g, fill = 0)
       r <- rollapplyr(m, k, sum, partial = TRUE)
       window(r, time(z))
    }
    

提交回复
热议问题