在rollapply()
的文档中,我注意到这可以滚动3天:
## rolling mean by time window (e.g., 3 days) rather than
## by number of observations (e.g., when these are unequally spaced):
#
## - test data
tt <- as.Date("2000-01-01") + c(1, 2, 5, 6, 7, 8, 10)
z <- zoo(seq_along(tt), tt)
## - fill it out to a daily series, zm, using NAs
## using a zero width zoo series g on a grid
g <- zoo(, seq(start(z), end(z), "day"))
zm <- merge(z, g)
## - 3-day rolling mean
rollapply(zm, 3, mean, na.rm = TRUE, fill = NA)
假设我有以下数据:
data.zoo <- read.zoo(
data.frame(
date = sample(seq(as.Date('2001-04-12'), as.Date("2019-04-05"), by="day"), 600),
val = runif(1:600),
val2 = runif(1:600)
))
是否可以将rollapply()
与5个月的滚动窗口一起使用来计算val
的滚动平均值? 5个月滚动窗口的问题在于一个月中的天数会有所不同...
注意:我希望使用base-R解决方案,但其他库也会很有趣
答案 0 :(得分:1)
由于width可以是宽度的向量,因此输入的每一行一个,因此我们可以简单地计算出每个日期与5个月前的天数,并将这些数字用作宽度向量:
library(zoo)
ym <- as.yearmon(time(data.zoo))
w <- as.Date(ym) - as.Date(ym - 5/12)
r <- rollapplyr(data.zoo, w, mean, fill = NA)
或者,我们可以用lubridate这样写w
。
library(lubridate)
w <- time(data.zoo) - (time(data.zoo) %m-% months(5))
如果可能缺少日期,则
library(lubridate)
w <- sapply(time(data.zoo), function(x)
length(intersect(seq(x %m-% months(5), x, "day"), time(data.zoo)))
或重复此操作,将%m-% months(5)
替换为subtract5m
,而不会使用其他软件包:
subtract5m <- function(x) {
if (length(x) == 1) seq(x, length = 2, by = "-5 month")[2]
else as.Date(sapply(x, subtract5m))
}
w <- sapply(time(data.zoo), function(x)
length(intersect(seq(subtract5m(x), x, "day"), time(data.zoo))))
请注意,由于5个月前的定义含糊不清,因此w的各种计算可能会基于略有不同的假设而略有不同。
答案 1 :(得分:0)
改进我所遵循的G. Grothendieck的想法:
ym <- as.yearmon(time(data.zoo))
ym.cutoff.ideal <- ym - 5/12
ym.cutoff.closest.to.ideal <- as.yearmon(time(data.zoo)[findInterval(as.Date(ym.cutoff.ideal), as.Date(ym)) + 1])
w <- time(data.zoo) - as.Date(ym.cutoff.closest.to.ideal) + 1
r <- rollapplyr(data.zoo, w, mean, fill = NA)
看起来工作正常...