Динамическое прогнозирование временных рядов и роллапли
Я пытаюсь получить скользящий прогноз динамической временной последовательности в R (а затем вывести квадратичные ошибки прогноза). Я основал большую часть этого кода на этом вопросе Stackru, но я очень плохо знаком с 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, как я ожидал (так как ширина 40)
- Прогнозы, которые он выдает, постоянны: 10.18676
Что я делаю неправильно? И есть ли более простой способ сделать прогноз, чем написать все это? Спасибо!
1 ответ
Основная проблема с вашей функцией - это data
аргумент dynlm
, Если вы посмотрите в ?dynlm
вы увидите, что data
аргумент должен быть data.frame
или zoo
объект. К сожалению, я только что узнал, что rollapply
разбивает ваш zoo
объекты в array
объекты. Это означает, что dynlm
, заметив, что ваш data
аргумент был не в правильной форме, искал x
а также y
в вашей глобальной среде, которые, конечно, были определены в верхней части вашего кода. Решение состоит в том, чтобы преобразовать 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
аргумент rollapply
, left
даст вам 1..60
, center
(по умолчанию) даст вам 20..80
а также right
получает вас 40..100
,