如何使用 5 个月 window 的 rollapply?
How can I use rollapply with a 5 month window?
我在 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 个月的滚动 window 来计算 val
的滚动平均值? 5 个月滚动的问题 window 是一个月中的天数变化...
注意:我更喜欢 base-R 解决方案,但其他库会很有趣
由于宽度可以是宽度的向量,输入的每一行一个宽度,我们可以简单地计算每个日期与 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 的各种计算可能略有不同。
改进 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)
看起来它工作正常...
我在 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 个月的滚动 window 来计算 val
的滚动平均值? 5 个月滚动的问题 window 是一个月中的天数变化...
注意:我更喜欢 base-R 解决方案,但其他库会很有趣
由于宽度可以是宽度的向量,输入的每一行一个宽度,我们可以简单地计算每个日期与 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 的各种计算可能略有不同。
改进 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)
看起来它工作正常...