为时间序列创建未来值的矩阵

时间:2011-11-15 17:32:45

标签: r time-series data-manipulation

我在R中有一个时间序列。我想构建一个矩阵,其中每一行都是当前观察,每一列代表该系列的未来值,从该点开始。例如:

x <- ts(1:25,start=2000, frequency=12)
maxHorizon <- 12

freq <- frequency(x)
st <- tsp(x)[1]-(1/freq)

actuals <- matrix(NA,length(x)-1,maxHorizon)
for(i in seq(1, (length(x)-1))) {
    xnext <- window(x, start=st+(i+1)/freq, end=st+(i+maxHorizon)/freq)
    actuals[i,1:length(xnext)] <- xnext
}
actuals

在这种情况下,我们有一个包含25个观测值的时间序列,因此我们的最终矩阵有24行。从第1行开始,接下来的12次挖掘是2-13。第2行是3-13等。在矩阵的末尾,我们用NA值填充它。

> x
     Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2000   1   2   3   4   5   6   7   8   9  10  11  12
2001  13  14  15  16  17  18  19  20  21  22  23  24
2002  25

> actuals
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    2    3    4    5    6    7    8    9   10    11    12    13
 [2,]    3    4    5    6    7    8    9   10   11    12    13    14
 [3,]    4    5    6    7    8    9   10   11   12    13    14    15
 [4,]    5    6    7    8    9   10   11   12   13    14    15    16
 [5,]    6    7    8    9   10   11   12   13   14    15    16    17
 [6,]    7    8    9   10   11   12   13   14   15    16    17    18
 [7,]    8    9   10   11   12   13   14   15   16    17    18    19
 [8,]    9   10   11   12   13   14   15   16   17    18    19    20
 [9,]   10   11   12   13   14   15   16   17   18    19    20    21
[10,]   11   12   13   14   15   16   17   18   19    20    21    22
[11,]   12   13   14   15   16   17   18   19   20    21    22    23
[12,]   13   14   15   16   17   18   19   20   21    22    23    24
[13,]   14   15   16   17   18   19   20   21   22    23    24    25
[14,]   15   16   17   18   19   20   21   22   23    24    25    NA
[15,]   16   17   18   19   20   21   22   23   24    25    NA    NA
[16,]   17   18   19   20   21   22   23   24   25    NA    NA    NA
[17,]   18   19   20   21   22   23   24   25   NA    NA    NA    NA
[18,]   19   20   21   22   23   24   25   NA   NA    NA    NA    NA
[19,]   20   21   22   23   24   25   NA   NA   NA    NA    NA    NA
[20,]   21   22   23   24   25   NA   NA   NA   NA    NA    NA    NA
[21,]   22   23   24   25   NA   NA   NA   NA   NA    NA    NA    NA
[22,]   23   24   25   NA   NA   NA   NA   NA   NA    NA    NA    NA
[23,]   24   25   NA   NA   NA   NA   NA   NA   NA    NA    NA    NA
[24,]   25   NA   NA   NA   NA   NA   NA   NA   NA    NA    NA    NA

如何在不使用丑陋for循环的情况下执行此操作?

编辑:如果数据以其他格式返回,例如data.frame甚至行列表,那就没问题了。

编辑:这里有一些代码来比较我们到目前为止的3个函数:

rm(list = ls(all = TRUE))

zach1 <- function(x,maxHorizon) {
    freq <- frequency(x)
    st <- tsp(x)[1]-(1/freq)

    actuals <- matrix(NA,length(x)-1,maxHorizon)

    for(i in seq(1, (length(x)-1))) {
        xnext <- window(x, start=st+(i+1)/freq, end=st+(i+maxHorizon)/freq)
        actuals[i,1:length(xnext)] <- xnext
    }

    actuals
}

zach2 <- function(x,maxHorizon) {
    t(apply(embed(c(x,rep(NA,maxHorizon)),maxHorizon),1,rev))[2:length(x),]
}

josh1 <- function(x,maxHorizon) {
    actuals <- outer(seq_along(x), seq_len(maxHorizon), FUN="+")
    actuals[actuals > length(x)] <- NA
    actuals <- actuals[1:(length(x)-1),]
    actuals <- apply(actuals,2,function(a) x[a])
    actuals
}

x <- ts(rnorm(10000),start=2000, frequency=12)

> system.time(actuals1 <- zach1(x, 6))
   user  system elapsed 
  11.81    0.00   11.93 

> system.time(actuals2 <- zach2(x, 6))
   user  system elapsed 
   0.15    0.00    0.16 

> system.time(actuals3 <- josh1(x, 6))
   user  system elapsed 
      0       0       0 

> all.equal(actuals1,actuals2)
[1] TRUE
> all.equal(actuals1,actuals3)
[1] TRUE

2 个答案:

答案 0 :(得分:2)

编辑:要使用x(而非索引)元素填充矩阵,您可以将outer()传递给您自己设计的“匿名函数”。这应该可以解决问题:

# Trying it out
x <- ts(rnorm(25),start=2000, frequency=12)
maxHorizon <- 12

actuals <- outer(seq_along(x), seq_len(maxHorizon), 
                 FUN = function(X,Y) {x[X+Y]}
)

tail(actuals)
#             [,1]       [,2]       [,3]       [,4]      [,5] [,6] [,7] [,8] [,9]
# [20,] -1.2729640 -0.4983060  0.6199497 -2.0999648 0.1673402   NA   NA   NA   NA
# [21,] -0.4983060  0.6199497 -2.0999648  0.1673402        NA   NA   NA   NA   NA
# [22,]  0.6199497 -2.0999648  0.1673402         NA        NA   NA   NA   NA   NA
# [23,] -2.0999648  0.1673402         NA         NA        NA   NA   NA   NA   NA
# [24,]  0.1673402         NA         NA         NA        NA   NA   NA   NA   NA
# [25,]         NA         NA         NA         NA        NA   NA   NA   NA   NA
#       [,10] [,11] [,12]
# [20,]    NA    NA    NA
# [21,]    NA    NA    NA
# [22,]    NA    NA    NA
# [23,]    NA    NA    NA
# [24,]    NA    NA    NA
# [25,]    NA    NA    NA

答案 1 :(得分:1)

这摆脱了for循环,但我不确定它是否更优雅: t(apply(embed(c(x,rep(NA,maxHorizon)),maxHorizon),1,rev))[2:length(x),]

编辑:但速度要快得多。