【问题标题】:Adding lagged variables to an lm model?将滞后变量添加到 lm 模型?
【发布时间】:2012-10-17 07:13:42
【问题描述】:

我在时间序列上使用 lm,实际上效果很好,而且超级超级快。

假设我的模型是:

> formula <- y ~ x

我在一个训练集上训练这个:

> train <- data.frame( x = seq(1,3), y = c(2,1,4) )
> model <- lm( formula, train )

...我可以对新数据进行预测:

> test <- data.frame( x = seq(4,6) )
> test$y <- predict( model, newdata = test )
> test
  x        y
1 4 4.333333
2 5 5.333333
3 6 6.333333

这非常好用,而且速度非常快。

我想在模型中添加滞后变量。现在,我可以通过扩充我的原始训练集来做到这一点:

> train$y_1 <- c(0,train$y[1:nrow(train)-1])
> train
  x y y_1
1 1 2   0
2 2 1   2
3 3 4   1

更新公式:

formula <- y ~ x * y_1

...训练会很好:

> model <- lm( formula, train )
> # no errors here

但是,问题在于无法使用“预测”,因为无法以批处理方式在测试集中填充 y_1。

现在,对于很多其他回归的东西,在公式中都有很方便的表达方式,比如poly(x,2)等,这些直接使用未经修改的训练和测试数据。

那么,我想知道公式中是否有某种方式来表达滞后变量,以便可以使用predict?理想情况下:

formula <- y ~ x * lag(y,-1)
model <- lm( formula, train )
test$y <- predict( model, newdata = test )

...无需扩充(不确定这是否是正确的词)训练和测试数据集,并且能够直接使用predict

【问题讨论】:

  • 这是我认为 R 应该能够更优雅地处理的东西。
  • @Charlie,这个问题被标记为“r”。你觉得上面的代码是用什么语言写的?
  • 我知道它是用 R 编写的。我只是评论说我认为 R 不能很好地处理时间序列操作(即使使用 dyn 包),我希望有一个可以更优雅地做到这一点的包。例如,我认为 Stata 使时间序列操作非常容易。 dyn 包有助于回归,但例如,将滞后变量添加到数据框需要一些技巧 df$lagged &lt;- c(NA, head(df$var, -1))
  • 啊,我明白了:“我希望它做到了”中的“应该”,而不是“我认为它做到了”中的“应该”。
  • 如果test 在覆盖之前包含列y,我认为您的代码的最后一块有效。

标签: r lm


【解决方案1】:

试试 ARIMA 函数。 AR 参数用于自回归,这意味着滞后 y。 xreg = 允许您添加其他 X 变量。您可以使用 predict.ARIMA 获得预测。

【讨论】:

    【解决方案2】:

    这是一个想法:

    为什么不创建一个新的数据框?用您需要的回归量填充数据框。您可以为所需的任何变量的所有滞后设置 L1、L2、...、Lp 之类的列,然后,您可以像使用横截面类型的回归一样使用函数。

    因为您不必每次调用拟合和预测函数时都对数据进行操作,而是对数据进行一次转换,因此速度会快很多。我知道 Eviews 和 Stata 提供了滞后的运营商。确实有一些方便。但是,如果您不需要像“lm”计算这样的所有功能,它也是低效的。如果您有数十万次迭代要执行,而您只需要预测,或预测和信息标准(如 BIC 或 AIC)的值,您可以通过避免进行您不会进行的计算来在速度上击败“lm”使用 -- 只需在函数中编写一个 OLS 估计器就可以了。

    【讨论】:

    • 你知道在行中添加滞后值作为列的任何实用方法吗?我认为我们需要一个所需滞后顺序的窗口,并将其通过日期转换以获得滞后值和相应的输出值。
    【解决方案3】:

    按照 Dirk 对 dynlm 的建议,我不太清楚如何预测,但通过搜索导致我通过 https://stats.stackexchange.com/questions/6758/1-step-ahead-predictions-with-dynlm-r-package 找到 dyn

    然后经过几个小时的实验,我想出了以下函数来处理预测。路上有很多“陷阱”,例如,你似乎看不到 rbind 时间序列,并且预测的结果被 start 和一大堆类似的东西所抵消,所以我觉得这个答案增加了与仅仅命名一个包相比,尽管我赞成 Dirk 的回答。

    所以,一个可行的解决方案是:

    • 使用dyn
    • 使用以下方法进行预测

    predictDyn 方法:

    # pass in training data, test data,
    # it will step through one by one
    # need to give dependent var name, so that it can make this into a timeseries
    predictDyn <- function( model, train, test, dependentvarname ) {
        Ntrain <- nrow(train)
        Ntest <- nrow(test)
        # can't rbind ts's apparently, so convert to numeric first
        train[,dependentvarname] <- as.numeric(train[,dependentvarname])
        test[,dependentvarname] <- as.numeric(test[,dependentvarname])
        testtraindata <- rbind( train, test )
        testtraindata[,dependentvarname] <- ts( as.numeric( testtraindata[,dependentvarname] ) )
        for( i in 1:Ntest ) {
           result <- predict(model,newdata=testtraindata,subset=1:(Ntrain+i-1))
           testtraindata[Ntrain+i,dependentvarname] <- result[Ntrain + i + 1 - start(result)][1]
        }
        return( testtraindata[(Ntrain+1):(Ntrain + Ntest),] )
    }
    

    示例用法:

    library("dyn")
    
    # size of training and test data
    N <- 6
    predictN <- 10
    
    # create training data, which we can get exact fit on, so we can check the results easily
    traindata <- c(1,2)
    for( i in 3:N ) { traindata[i] <- 0.5 + 1.3 * traindata[i-2] + 1.7 * traindata[i-1] }
    train <- data.frame( y = ts( traindata ), foo = 1)
    
    # create testing data, bunch of NAs
    test <- data.frame( y = ts( rep(NA,predictN) ), foo = 1)
    
    # fit a model
    model <- dyn$lm( y ~ lag(y,-1) + lag(y,-2), train )
    # look at the model, it's a perfect fit. Nice!
    print(model)
    
    test <- predictDyn( model, train, test, "y" )
    print(test)
    
    # nice plot
    plot(test$y, type='l')
    

    输出:

    > model
    
    Call:
    lm(formula = dyn(y ~ lag(y, -1) + lag(y, -2)), data = train)
    
    Coefficients:
    (Intercept)   lag(y, -1)   lag(y, -2)  
            0.5          1.7          1.3  
    
    > test
                 y foo
    7     143.2054   1
    8     325.6810   1
    9     740.3247   1
    10   1682.4373   1
    11   3823.0656   1
    12   8686.8801   1
    13  19738.1816   1
    14  44848.3528   1
    15 101902.3358   1
    16 231537.3296   1
    

    编辑:嗯,这虽然超级慢。即使我将 subset 中的数据限制为数据集中的固定几行,每次预测也需要大约 24 毫秒,或者,对于我的任务,0.024*7*24*8*20*10/60/60 = 1.792 hours :-O

    【讨论】:

      【解决方案4】:

      看看例如dynlm 包为您提供滞后运算符。更一般地说,计量经济学和时间序列的任务视图将有更多内容供您查看。

      这里是它的例子的开始——一个和十二个月的滞后:

      R>      data("UKDriverDeaths", package = "datasets")
      R>      uk <- log10(UKDriverDeaths)
      R>      dfm <- dynlm(uk ~ L(uk, 1) + L(uk, 12))
      R>      dfm
      
      Time series regression with "ts" data:
      Start = 1970(1), End = 1984(12)
      
      Call:
      dynlm(formula = uk ~ L(uk, 1) + L(uk, 12))
      
      Coefficients:
      (Intercept)     L(uk, 1)    L(uk, 12)  
            0.183        0.431        0.511  
      
      R> 
      

      【讨论】:

      • 如果你有时间,我如何处理测试数据?即,如果我在train &lt;- data.frame( y = head(UKDriverDeaths,96) ) 上进行训练,然后将我的测试数据设置为test &lt;- data.frame( y = rep(UKDriverDeaths[97],96) ),我会得到一条水平直线,即它使用的是我的测试数据集中y 的滞后值,而不是使用计算值。 (编辑:使用 NA 没有更好的方法,即test &lt;- data.frame( y = c( UKDriverDeaths[97], rep(NA, 95) ) ):它只是为所有内容提供NA)(编辑2:哦,也许使用update?)
      • 似乎无法弄清楚如何让它预测。 update(model,end=192) 似乎不起作用,model &lt;- dynlm( y ~ L(y,1), end= 192) 也不起作用。
      • 更新了我尝试使用dyn 库的问题,该库至少在语义上与dynlm 库相关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-09
      • 2012-12-26
      • 1970-01-01
      • 2019-10-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多