时间窗不恒定时运行差异

时间:2015-06-18 11:56:45

标签: r variance sliding-window

我正在尝试为names ABC中的每一个计算带有窗口的移动方差,比如说4年。数据是每周一次:

> head(data1, 17)
         date name       value
1  1985-01-01    A -0.44008233
2  1985-01-01    B          NA #Observe that there are some NA's
3  1985-01-01    C  0.38682496
4  1985-01-08    A  0.41806540
5  1985-01-08    B -0.05460831
6  1985-01-08    C -0.52051435
7  1985-01-15    A  1.25769395
8  1985-01-15    B  0.80272053
9  1985-01-15    C -0.34501742
10 1985-01-22    A -0.43401839
11 1985-01-22    B  0.91113966
12 1985-01-22    C  1.07131717
13 1985-01-29    A -1.55395857
14 1985-01-29    B -0.43281709
15 1985-01-29    C  0.98034779
16 1985-02-05    A  1.70557396
17 1985-02-05    B  0.44688788

到目前为止,我的方法是dcast数据,然后以{= 1}}(rollapply())列方式运行,移动窗口为192 = 4 * 12 * 4:

zoo

然而,我意识到在几个月内我有四个观察结果(例如2月7,14,21,28),而对于一些人来说,我每周都有五个观察结果(例如,1月1日,8日,15日,22日和29日),因此使用v <- dcast(data1, date ~ name, value.var = "value") var <- rollapply(v[-1], width=4*12*4, var, fill=NA, by.column = T) var <- cbind(v$date, var) var[,1] <- as.Date(var[,1]) 观察窗口是不正确的。我想在时间窗口(4 years * 12 months * 4 weeks)上添加这些额外的观察,但我不确定如何(或者甚至是否可能),因为这些变化取决于每月5周的数量和在时间窗口内有多少4个星期的每月观察结果。

此外,我希望在移动时间窗口内有width个观察时NA(我认为这会由NA自动处理)并且我也希望忽略零观察。为此,我想我可以在运行运行方差函数之前删除零,然后以某种方式将它们放回最后。所以你可以忽略那一部分,当然,除非你有一个好主意,一步到位。

示例数据

var()

2 个答案:

答案 0 :(得分:2)

我认为您的滚动窗口应该与数据中的周数重合。它只是一个数据窗口来平滑它。一个想法是用2个窗口做一些事情并取平均值:

library(data.table)
library(zoo)
setDT(data1)[,var := {
           v1 <- rollapplyr(value,width=4*12*4, var, fill=N)
           v2 <- rollapplyr(value,width=4*12*5, var, fill=N)
           (v1+v2)/2},  name]

PS:我在这里使用data.table,因为它适用于拆分(每组)和重新绑定操作。

修改

您还可以将每周数据转换为每日数据,然后您可以在此基础上计算更准确的滚动数据。我们的想法是创建每日索引并将其与原始数据合并。这将创建一个缺少值的新data.table。您可以使用na.locf将缺少的值替换为第一个非缺失值。

library(data.table)
library(zoo)
ID <- 
data.table(
  date = seq(as.Date("1985-01-01"), as.Date("2010-01-1"), by="days"))
setkey(ID,date)

setDT(data1)[,date:=as.Date(date)][, 
        {
          merge(ID,.SD,all.x=TRUE)[,value := na.locf(value)]
        },

        name]

答案 1 :(得分:2)

4年有208周加5天所以它不能平均分成几周。如果我们使用209周,那么我们在4年内只有2天,所以让我们尝试一下。

首先将data1转换为"zoo"类,根据第二列的值将数据拆分为单独的列。对于zAB,每个C都会有一列。然后定义一个方差函数,该函数排除零并将其与rollapplyr

一起使用
library(zoo)
z <- read.zoo(data1, split = 2) # 1305 x 3 
var0 <- function(x) var(x[x != 0])
r <- rollapplyr(z, 209, var0)

将其保留为动物园对象可能就足够了,但这会将其转换为包含IndexABC列的4列数据框:< / p>

fortify.zoo(r)