根据函数计算具有不规则间距的时间序列的加权和

时间:2018-04-23 21:55:35

标签: r dplyr zoo

给定一个包含时间序列的数据帧,该时间序列具有不规则间隔,定义为:

df <- data.frame(date = as.Date("2016-01-01") + ((1:100) + sample(1:5, 100, replace = TRUE)), 
data = rnorm(100) )

如何计算过去30天内data列的滚动总和,并使用此衰减函数定义权重?

tau <- 0.05
decay = function(tau, day){
  exp(-tau * day)
}

当天的数据的权重为1,而30天前的数据的权重为decay(0.05, 30) = 0.2231302。在使用衰减函数计算权重时,仍应考虑输入时间序列中的缺失天数。

如果可能,我想将数据框转换为zooxts对象,然后使用rollapplyr函数或类似函数,并使用{{1}执行此操作管道。

2 个答案:

答案 0 :(得分:2)

定义一个函数weighted,该函数占用最后30个点,而这些点仅保留在最后一个点的30天内的点数。然后使用那些乘以权重。

在管道中,我们将df转换为动物园,然后将rollapplyrweighted一起使用。请注意,我们必须使用coredata = FALSE,以便将时间索引传递给weighted。没有它就不会。

library(dplyr)
library(zoo)

weighted <- function(x, tau) {
  tx <- time(x)
  cx <- coredata(x)[tx > tail(tx, 1) - 30] # only keep if within 30 days
  w <- decay(tau, seq(to = 0, by = -1, length = length(cx)) )
  sum(w * cx)
}

df %>%
  read.zoo %>%
  rollapplyr(30, weighted, tau = tau, partial = TRUE, coredata = FALSE)

如果您想将缺失的天数视为0,请改为使用此代码:

weighted <- function(x, tau) {
  tx <- as.numeric(time(x))
  days <- tail(tx, 1) - tx
  w <- (days < 30) * decay(tau, days)
  sum(w * coredata(x))
}

注意

我们通过添加set.seed来重现性,使用了从问题修改的以下输入。此外,问题中使用的代码可能偶然会产生具有相同date的多个值,并且我们消除了这样的重复。

set.seed(123)
df <- data.frame(date = as.Date("2016-01-01") + 1:100 + sample(1:5, 100, replace = TRUE), 
  data = rnorm(100) )
df <- df[!duplicated(df$date), ]

tau <- 0.05
decay = function(tau, day){
  exp(-tau * day)
}

答案 1 :(得分:0)

我不确定管道,但这应该让你去:

d <- decay(tau, 29:0)
rollapply(df, 30, function(z) {
  data <- as.data.frame(z, stringsAsFactors = FALSE)
  data$data <- as.numeric(data$data)
  sum(data$data * d)
}, by.column = FALSE)