【问题标题】:Creating a matrix of future values for a time series为时间序列创建未来值矩阵
【发布时间】:2011-12-29 17:55:51
【问题描述】:

我在 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

【问题讨论】:

    标签: r time-series data-manipulation


    【解决方案1】:

    编辑:要用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
    

    【讨论】:

    • 如果我的 x 不是序列怎么办?如果它是一个向量怎么办,比如x &lt;- ts(rnorm(25),start=2000, frequency=12)
    • 我不太清楚你的意思。 seq_along(x) 返回向量 c(1,2,3...,24,25)。你想要别的东西吗?
    • 我希望最终矩阵返回 x 的实际值,而不是索引。所以你的方法需要最后一步,比如apply(actuals,2,function(a) x[a])。我想这很容易添加。
    【解决方案2】:

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

    编辑:不过速度要快得多。

    【讨论】:

      猜你喜欢
      • 2014-09-19
      • 1970-01-01
      • 2015-03-24
      • 2014-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多