Как использовать auto.arima для вменения пропущенных значений

12

У меня есть серия зоопарка со многими пропущенными значениями. Я читал, что auto.arimaможет вменять эти пропущенные значения? Может кто-нибудь может научить меня, как это сделать? большое спасибо!

Это то, что я пытался, но безуспешно:

fit <- auto.arima(tsx)
plot(forecast(fit))
user3730957
источник
Как дополнение к javlacalle и моему ответу ниже: я реализовал их в пакете imputeTS. Функция называется na.kalman и выполняет сглаживание Калмана для формы пространства состояний модели ARIMA
stats0007

Ответы:

25

Во-первых, имейте в 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,]

Работа с отсутствующими наблюдениями с помощью фильтра Калмана иногда интерпретируется как экстраполяция ряда; когда используется сглаживатель Калмана, пропущенные наблюдения, как говорят, заполняются путем интерполяции в наблюдаемом ряду.

javlacalle
источник
Привет Javlacalle, большое спасибо за вашу помощь. Могу ли я спросить, есть ли какое-либо условие для временного ряда, или это может применяться для любого? Не могли бы вы немного рассказать об этих командных строках? tmp <- which (соответствует Z == 1) id <- ifelse (length (tmp) == 1, tmp [1], tmp [2])model
user3730957
Я еще раз проверил, как makeARIMAопределяются матрицы формы пространства состояний, и я бы сказал, что столбец, принятый в, idявляется правильным. Вектор в уравнении наблюдения определяется makeARIMAкак:, Z <- c(1, rep.int(0, r - 1L), Delta)где Delta- вектор, содержащий коэффициенты разностного фильтра. Если разностного фильтра нет (т. Е. Модель ARMA length(tmp)==1), тогда idдолжно быть 1; в противном случае первый столбец относится к разностному ряду, а следующий элемент, Zпринимающий значение 1, относится к , индексу, который следует взять. yt1
Javlacalle
1
@ user3730957 Я обновил свой ответ, исправляя эту проблему с помощью индексации.
Javlacalle
2

Вот мое решение:

# Take AirPassengers as example
data <- AirPassengers

# Set missing values
data[c(44,45,88,90,111,122,129,130,135,136)] <- NA


missindx <- is.na(data)

arimaModel <- auto.arima(data)
model <- arimaModel$model

#Kalman smoothing
kal <- KalmanSmooth(data, model, nit )
erg <- kal$smooth  

for ( i in 1:length(model$Z)) {
       erg[,i] = erg[,i] * model$Z[i]
}
karima <-rowSums(erg)

for (i in 1:length(data)) {
  if (is.na(data[i])) {
    data[i] <- karima[i]
  }
}
#Original TimeSeries with imputed values
print(data)

@ Javlacalle:

Спасибо за ваш пост, очень интересно!

У меня есть два вопроса к вашему решению, надеюсь, вы поможете мне:

  1. Почему вы используете KalmanRun вместо KalmanSmooth? Я читал, что KalmanRun считается экстраполяцией, тогда как сглаживание будет оценкой.

  2. Я также не получаю вашу часть удостоверения личности. Почему вы не используете все компоненты в .Z? Я имею в виду, например .Z дает 1, 0,0,0,0,1, -1 -> 7 значений. Это значит, что .smooth (в вашем случае для состояний KalmanRun) дает мне 7 столбцов. Как я понимаю, все столбцы, которые равны 1 или -1, входят в модель.

    Допустим, строка 5 отсутствует в AirPass. Тогда я бы взял сумму строки 5 следующим образом: я бы добавил значение из столбца 1 (потому что Z дал 1), я бы не добавил столбец 2-4 (потому что Z говорит 0), я бы добавил столбец 5, и я бы добавить отрицательное значение столбца 7 (потому что Z говорит -1)

    Мое решение неверно? Или они оба в порядке? Можете ли вы объяснить мне дальше?

stats0007
источник
Я бы порекомендовал опубликовать вторую часть вашего ответа в виде комментариев к сообщению @ Javlacalle, а не в пределах вашего собственного ответа.
Патрик Куломб
пытался ... но он говорит, что я должен иметь 50 репутации, чтобы комментировать
stats0007