Во-первых, имейте в forecast
виду, что вычисление прогнозов вне выборки, но вы заинтересованы в наблюдениях в выборке.
Фильтр Калмана обрабатывает пропущенные значения. Таким образом, вы можете взять форму пространства состояний модели ARIMA из выходных данных, возвращенных forecast::auto.arima
или, stats::arima
и передать ее KalmanRun
.
Изменить (исправить в коде на основе ответа stats0007)
В предыдущей версии я взял столбец отфильтрованных состояний, относящихся к наблюдаемому ряду, однако я должен использовать всю матрицу и выполнить соответствующую матричную операцию уравнения наблюдения, . (Спасибо @ stats0007 за комментарии.) Ниже я обновляю код и строю график соответственно.yt=Zαt
Я использую ts
объект в качестве образца серии zoo
, но он должен быть таким же:
require(forecast)
# sample series
x0 <- x <- log(AirPassengers)
y <- x
# set some missing values
x[c(10,60:71,100,130)] <- NA
# fit model
fit <- auto.arima(x)
# Kalman filter
kr <- KalmanRun(x, fit$model)
# impute missing values Z %*% alpha at each missing observation
id.na <- which(is.na(x))
for (i in id.na)
y[i] <- fit$model$Z %*% kr$states[i,]
# alternative to the explicit loop above
sapply(id.na, FUN = function(x, Z, alpha) Z %*% alpha[x,],
Z = fit$model$Z, alpha = kr$states)
y[id.na]
# [1] 4.767653 5.348100 5.364654 5.397167 5.523751 5.478211 5.482107 5.593442
# [9] 5.666549 5.701984 5.569021 5.463723 5.339286 5.855145 6.005067
Вы можете построить результат (для всей серии и для всего года с отсутствующими наблюдениями в середине выборки):
par(mfrow = c(2, 1), mar = c(2.2,2.2,2,2))
plot(x0, col = "gray")
lines(x)
points(time(x0)[id.na], x0[id.na], col = "blue", pch = 19)
points(time(y)[id.na], y[id.na], col = "red", pch = 17)
legend("topleft", legend = c("true values", "imputed values"),
col = c("blue", "red"), pch = c(19, 17))
plot(time(x0)[60:71], x0[60:71], type = "b", col = "blue",
pch = 19, ylim = range(x0[60:71]))
points(time(y)[60:71], y[60:71], col = "red", pch = 17)
lines(time(y)[60:71], y[60:71], col = "red")
legend("topleft", legend = c("true values", "imputed values"),
col = c("blue", "red"), pch = c(19, 17), lty = c(1, 1))
Вы можете повторить тот же пример, используя сглаживатель Калмана вместо фильтра Калмана. Все, что вам нужно изменить, это следующие строки:
kr <- KalmanSmooth(x, fit$model)
y[i] <- kr$smooth[i,]
Работа с отсутствующими наблюдениями с помощью фильтра Калмана иногда интерпретируется как экстраполяция ряда; когда используется сглаживатель Калмана, пропущенные наблюдения, как говорят, заполняются путем интерполяции в наблюдаемом ряду.