2012-07-20 27 views
1

我试图获得R中动态时间序列的滚动预测(然后计算预测的平方误差)。我基于this StackOverflow question上的很多代码,但我对R非常陌生,所以我挣扎了很多。任何帮助将非常感激。动态时间序列预测和滚动

require(zoo) 
require(dynlm) 

set.seed(12345) 
#create variables 
x<-rnorm(mean=3,sd=2,100) 
y<-rep(NA,100) 
y[1]<-x[1] 
for(i in 2:100) y[i]=1+x[i-1]+0.5*y[i-1]+rnorm(1,0,0.5) 
int<-1:100 
dummydata<-data.frame(int=int,x=x,y=y) 

zoodata<-as.zoo(dummydata) 

prediction<-function(series) 
    { 
    mod<-dynlm(formula = y ~ L(y) + L(x), data = series) #get model 
    nextOb<-nrow(series)+1 
    #make forecast 
    predicted<-coef(mod)[1]+coef(mod)[2]*zoodata$y[nextOb-1]+coef(mod)[3]*zoodata$x[nextOb-1] 

    #strip timeseries information 
    attributes(predicted)<-NULL 

    return(predicted) 
    }     

rolling<-rollapply(zoodata,width=40,FUN=prediction,by.column=FALSE) 

这将返回:

20   21  .....  80 
10.18676 10.18676   10.18676 

里面有两个问题,我没想到:从20-> 80,不40-> 100我希望

  1. 奔跑(如宽度为40)
  2. 它给出的预测值是常数:10.18676

我在做什么错?有没有更容易的方法来做预测,而不是全部写出来?谢谢!

回答

2

你的功能的主要问题是data参数dynlm。如果您查看?dynlm,您会看到参数data必须是data.framezoo对象。不幸的是,我刚刚了解到rollapply会将您的zoo对象拆分为array对象。这意味着dynlm在注意到您的data参数不正确之后,在您的全球环境中搜索了xy,这些环境当然是在您的代码顶部定义的。解决方案是将series转换为zoo对象。有一对夫妇与你的代码的其他问题,我在这里发布修正版本:

prediction<-function(series) { 
    mod <- dynlm(formula = y ~ L(y) + L(x), data = as.zoo(series)) # get model 
    # nextOb <- nrow(series)+1 # This will always be 21. I think you mean: 
    nextOb <- max(series[,'int'])+1 # To get the first row that follows the window 
    if (nextOb<=nrow(zoodata)) { # You won't predict the last one 
    # make forecast 
    # predicted<-coef(mod)[1]+coef(mod)[2]*zoodata$y[nextOb-1]+coef(mod)[3]*zoodata$x[nextOb-1] 
    # That would work, but there is a very nice function called predict 
    predicted=predict(mod,newdata=data.frame(x=zoodata[nextOb,'x'],y=zoodata[nextOb,'y'])) 
    # I'm not sure why you used nextOb-1 
    attributes(predicted)<-NULL 
    # I added the square error as well as the prediction. 
    c(predicted=predicted,square.res=(predicted-zoodata[nextOb,'y'])^2) 
    } 
}  

rollapply(zoodata,width=20,FUN=prediction,by.column=F,align='right') 

你的第二个问题,关于你的结果的编号,可以通过align参数进行控制是rollapplyleft会给你1..60,center(默认)会给你20..80right得到你40..100

+0

非常感谢!完美的作品! – MatthewK 2012-07-21 02:56:05