Сбросить cumprod в функции - PullRequest
0 голосов
/ 22 июня 2019

Я пытаюсь создать функцию для расчета скользящего cumprod. Функция должна учитывать скользящее окно. Я получил следующие данные:

set.seed(1)
library(zoo)
test1 <- data.table(time=as.yearmon(2000 + seq(0, 35)/12),a=rep(1:12,3),outcome1=rep(cumprod(1:12),3))
test2 <- data.table(time=as.yearmon(2000 + seq(0, 35)/12),a=rep(rnorm(36)))
test2[,outcome2:=c(NA,NA,cumprod(test2$a[3:8]),rep(NA,6),cumprod(test2$a[15:20]),rep(NA,6),cumprod(test2$a[27:32]),rep(NA,4))]

test1 просто вычисляет cumprod за 12 месяцев, затем снова и т. Д., Чтобы проиллюстрировать идею без скользящего окна. test2 показывает предполагаемый расчет: cumprod с примерного марта по август, затем пустое окно в 6 месяцев, прежде чем следующий расчет начнется в марте следующего года.

Некоторое время назад я пытался создать решение, которое вручную вычисляло бы начальную и конечную точки для довольно большого набора данных, но функция внутри цикла была слишком медленной / неосуществимой. Я считаю, что с zoo это может быть быстрее. Я тестировал следующее:

rollapply(c(1:12,1:12), width = 12, prod, partial = TRUE, align = "right")

.. но до сих пор не удалось заставить его правильно сброситься через 12 месяцев. Кроме того, добавление окна с by внутри rollapply было невозможно. Любые советы приветствуются!

Обратите внимание, что мой полный набор данных не всегда начинается в январе, поэтому индексация не так проста. Я хотел избежать панели здесь, чтобы сделать ее простой.

1 Ответ

1 голос
/ 23 июня 2019

Если ym является вектором года, тогда as.integer(ym) является годом, а cycle(ym) является номером месяца, поэтому:

test1[, out := cumprod(a), by = as.integer(time)] 

test2[, out := cumprod(ifelse(cycle(time) %in% 3:8, a, NA)), 
  by = .(as.integer(time), cycle(time) %in% 3:8)]
...