Search code examples
rdata.tablelapplyrollapply

Combining rollapply() and weighted.mean() in a data.table apply() for multiple columns


I am trying to compute weighted averages for various columns in data.table with rollapply() and weighted.mean() as follows:

DT <- data.table(id = rep(c(1,2), each = 5),
                 var1 = 1:10,
                 var2 = 11:20)
col_names <- c('var1', 'var2')
DT[, (col_names) := lapply(.SD, 
                           function(x) rollapplyr(x, 
                                                  width = 3,
                                                  weighted.mean, 
                                                  w = c(0.2, 0.3, 0.5),
                                                  align = 'right', 
                                                  partial = TRUE, 
                                                  na.rm = TRUE)),
   by = id,
   .SDcols = col_names]

However, I get the error:

Error in weighted.mean.default(data[replace(posns, !ix, 0)], ...) : 
  'x' and 'w' must have the same length 

Is it because .SD is a data.table and weighted.mean() doesn't work for data.tables?

Is there a way to make it work?


Solution

  • If we remove the partial = TRUE, it should work along with adding fill = NA

    library(data.table)
    DT[, (col_names) := lapply(.SD, 
                               function(x) rollapplyr(x, 
                                                      width = 3,
                                                      weighted.mean, 
                                                      w = c(0.2, 0.3, 0.5),
                                                      align = 'right', 
                                                      fill = NA
                                                      )),
       by = id,
       .SDcols = col_names]
    

    With partial = TRUE, the 'w' length is same as 3 and there is no subsetting which creates the error in length difference between 'x' and 'w'