除可变长度外,不能选择预测的期间数

Can not choose number of periods for forecasting any other than variable length

我想根据我使用 forecast 包中的 tslm 估计的模型预测时间序列。这是一些数据:

x <- ts(rnorm(120,0,3) + 1:120 + 20*sin(2*pi*(1:120)/12), frequency=12, start= c(2000, 01, 01))
y <- ts(x + rnorm(length(x)), frequency=12, start= c(2000, 01, 01))
df <- data.frame(y, x)

所以我们有一个具有某种模式的(独立)变量 x 和一个(因)变量 y,它似乎是 x 的噪声版本。我适合这样的模型:

fit <- tslm(y ~ trend + season + x, df)

summary(fit) 看起来不错,因为 x 非常重要并且估计值接近 1。但是 运行 forecast(fit, h=20) 给我一个错误:

... variable lengths differ (found for 'x') ...

forecast(fit, h= length(x)) 有效(虽然 plot(forecast(fit, h= length(x))) 看起来很奇怪,但这是另一个问题)。

使用 xtrendseasonal 等预测变量预测 y 的未来, 必须为您要预测的提前期数提供预测变量的新数据。 这可以使用 forecast.lm 中的参数 newdata 来完成(参见 ?forecast.lm

下面是一个仅以 x 作为预测变量的示例,我们希望在接下来的 12 个月中预测 y

library(forecast)
n <- 132 
set.seed(1337)
x <- ts(rnorm(n,0,3) + 1:n + 20*sin(2*pi*(1:n)/12), frequency=12, start= c(2000, 01, 01))
#Dividing x into a train and test set, where the test set will be the data we use to forecast ´y´
xtrain <- window(x, end=c(2009, 12))
xtest <- data.frame(x=window(x, start=c(2010, 1)))
y <- window(ts(x + rnorm(length(x)), frequency=12, start= c(2000, 01, 01)), end=c(2009,12))
dftrain <- data.frame(y, x=xtrain)

fit <- tslm(y ~ x, dftrain)
f <- forecast(fit, newdata=xtest)
plot(f)

tslm 函数有点 'special' 的原因在于,如果指定,它会自动生成趋势和季节性数据,例如

fit2 <- tslm(y~trend+season)
f2 <- forecast(fit2, h=12)
plot(f2)

这里它自动为newdata参数生成数据,可以在这里找到:

f2$newdata #Beware, season is a factor: str(f2$newdata)

如果我们结合趋势、季节和 x,我们得到

fit3 <- tslm(y~trend+season+x, data=dftrain)
f3 <- forecast(fit3, newdata=xtest)
f3$newdata 

奇怪!尽管我们希望它使用所有预测变量进行预测,但 f$newdata 中不包括趋势和季节。我们可以尝试手动包含趋势和季节性并检查我们是否得到相同的结果:

#Using `seasonaldummy` from the `forecast` package to generate the seasonal dummy matrix. 
#Beware: `forecast::seasonaldummy` use December as reference period by default, while `tslm` use January.
#This should not affect our results, except for the interpretation of the seasonal coefficients.
dftrain2 <- data.frame(y, x=xtrain, customTrend=1:(n-12), forecast::seasonaldummy(xtrain))
dftest2 <- data.frame(x=xtest, customTrend = (n-12+1):n, forecast::seasonaldummy(xtrain, h=12))
fit4 <- tslm(y~customTrend+Jan+Feb+Mar+Apr+May+Jun+Jul+Aug+Sep+Oct+Nov+x, data=dftrain2)
f4 <- forecast(fit4, newdata = dftest2)

f4$newdata #now everything is included. 

#Compare the forecasts generated by fit3 and fit4:
f3$mean - f4$mean #Close enough
all.equal(f3$mean, f4$mean) #Point forecast
all.equal(f3$lower, f4$lower) #PIs
all.equal(f3$upper, f4$upper) #PIs

我们还可以将季节性变量包括为 factor,这更容易一些(但在我看来不太直观),并且会产生与 fit3.[=30= 完全相同的系数估计值]

dftrain3 <- data.frame(y, x=xtrain, customTrend=1:(n-12), customSeason = rep(factor(1:12, levels=1:12), 10))
dftest3 <- data.frame(x=xtest, customTrend = (n-12+1):n, customSeason = factor(1:12, levels=1:12))
fit5 <- tslm(y~customTrend+customSeason+x, data=dftrain3)
all(coefficients(fit3) == coefficients(fit5))
f5 <- forecast(fit5, newdata = dftest3)
f5$newdata