RcppRoll или CumSum для отставания с окном Dynami c - PullRequest
2 голосов
/ 28 января 2020

Должно быть простое, возможное рекурсивное решение для следующей проблемы. Я был бы очень признателен, если кто-нибудь может помочь:

Я использую data.table и RcppRoll для расчета еженедельных продаж в квалифицированные недели за последние 26 недель для каждого продукта. С окном 26 это работает нормально, если число текущей недели> 26. Однако, когда число текущей недели <= 26, я хочу использовать окно размером 26, 25, ... и т. Д. на. </p>

Формула будет: базовые продажи = сумма за 26 (или менее) недель продаж (до текущей недели, только в квалифицированных неделях), деленная на число квалифицированных недель

Здесь это некоторый код для создания тестовых данных:

library("data.table")
library("RcppRoll")

products <- seq(1:10) #grouping variable
weeks <- seq(1:100) #weeks
sales <- round(rchisq(1000, 2),0) #sales
countweek <- round(runif(1000, 0,1),0) #1, if qualified weeks

data <- as.data.table(cbind(merge(weeks,products,all=T),sales,countweek))
names(data) <- c("week","product","sales","countweek")
data <- data[order(product,week)]

data[,pastsales:=shift(RcppRoll::roll_sumr(sales*countweek,26L,fill=0),1L,0,"lag"),by=.(product)]
data[,rollweekcount:=shift(RcppRoll::roll_sumr(countweek,26L,fill=0),1L,0,"lag"),by=.(product)]
data[,baseline:=pastsales/rollweekcount]

Вы можете увидеть разрыв на строке 26 недели для продукта 1. После строки 26 я получаю желаемые результаты:

> data[product == 1]
     week product sales countweek pastsales rollweekcount baseline
...
 20:   20       1     1         0         0             0      NaN
 21:   21       1     2         0         0             0      NaN
 22:   22       1     1         1         0             0      NaN
 23:   23       1     0         0         0             0      NaN
 24:   24       1     3         1         0             0      NaN
 25:   25       1     5         1         0             0      NaN
 26:   26       1     5         1         0             0      NaN
 27:   27       1     1         1        44            13 3.384615
 28:   28       1     0         1        45            14 3.214286
 29:   29       1     5         0        44            14 3.142857
 30:   30       1     0         1        44            14 3.142857
 31:   31       1     3         1        44            14 3.142857
 32:   32       1     4         0        42            14 3.000000
...

1 Ответ

4 голосов
/ 28 января 2020

Вам нужна «адаптивная» ширина окна. Не уверен насчет RcppRoll, но в последних версиях data.table есть frollsum, который может это сделать

data[, pastsales := shift(frollsum(sales*countweek, pmin(1:.N, 26L), adaptive = TRUE),
                          1L, 0, "lag"),
     by = .(product)]

data[, rollweekcount := shift(frollsum(countweek,  pmin(1:.N,  26L), adaptive = TRUE), 
                              1L, 0, "lag"), 
     by = .(product)]
...