您正在尝试预测组成时间序列。也就是说,您有三个分量都被限制在 0 和 1 之间并且加起来等于 1。
您可以通过使用适当的广义逻辑变换来使用标准指数平滑来解决此问题。Koehler、Snyder、Ord 和 Beaumont在 2010 年国际预测研讨会上对此进行了介绍,并发表了一篇论文(Snyder 等人,2017 年,国际预测杂志)。
让我们用你的数据来看看这个。将数据读入obs时间序列矩阵:
obs <- structure(c(0.03333333, 0.03810624, 0, 0.03776683, 0.06606607,
0.03900325, 0.03125, 0, 0.04927885, 0.0610687, 0.03846154, 0,
0.06028636, 0.09646302, 0.04444444, 0.01111111, 0.02309469, 0.03846154,
0.03119869, 0.01201201, 0.02058505, 0.015625, 0, 0.01802885,
0.02290076, 0, 0, 0.03843256, 0.05144695, 0.06666667, 0.9555556,
0.9387991, 0.9615385, 0.9310345, 0.9219219, 0.9404117, 0.953125,
1, 0.9326923, 0.9160305, 0.9615385, 1, 0.9012811, 0.85209, 0.8888889
), .Dim = c(15L, 3L), .Dimnames = list(NULL, c("Series 1", "Series 2",
"Series 3")), .Tsp = c(1, 15, 1), class = c("mts", "ts", "matrix"
))
您可以通过键入来检查这是否有效
obs
现在,你有几个零,一旦你取对数,这将是一个问题。一个简单的解决方案是设置小于小的所有内容ϵ到那个ϵ:
epsilon <- 0.0001
obs[obs<epsilon] <- epsilon
现在修改后的行不再总和为 1。我们可以纠正这一点(尽管我认为这可能会使预测变得更糟):
obs <- obs/matrix(rowSums(obs),nrow=nrow(obs),ncol=ncol(obs),byrow=FALSE)
现在我们按照演示文稿的第 35 页转换数据:
zz <- log(obs[,-ncol(obs)]/obs[,ncol(obs)])
colnames(zz) <- head(colnames(obs),-1)
zz
加载forecast包并设置 5 个时间点的范围:
library(forecast)
horizon <- 5
现在逐列建模和预测转换后的数据。这里我只是调用ets(),它将尝试拟合状态空间指数平滑模型。事实证明,它对所有三个系列都使用单指数平滑,但特别是如果您有超过 15 个时间段,它可能会选择趋势模型。或者,如果您有月度数据,请向 R 解释您有潜在的季节性,使用ts()with frequency=12- 然后ets()查看季节性模型。
baz <- apply(zz,2,function(xx)forecast(ets(xx),horizon=horizon)["mean"])
forecasts.transformed <- cbind(baz[[1]]$mean,baz[[2]]$mean)
接下来,我们根据演示文稿的第 38 页对预测进行反向转换:
forecasts <- cbind(exp(forecasts.transformed),1)/(1+rowSums(exp(forecasts.transformed)))
最后,让我们绘制历史和预测:
plot(obs[,1],ylim=c(0,1),xlim=c(1,nrow(obs)+horizon),type="n",ylab="")
for ( ii in 1:ncol(obs) ) {
lines(obs[,ii],type="o",pch=19,col=ii)
lines(forecasts[,ii],type="o",pch=21,col=ii,lty=2)
}
legend("left",inset=.01,lwd=1,col=1:ncol(obs),pch=19,legend=colnames(obs))

编辑:一篇关于成分时间序列预测的论文刚刚出现。我没读过,但可能很有趣。