Як використовувати auto.arima для присвоєння відсутніх значень


12

У мене є серія зоопарків з багатьма відсутніми значеннями. Я читав, що auto.arimaможе імпулювати ці відсутні значення? Хтось може навчити мене, як це зробити? дуже дякую!

Це те, що я спробував, але без успіху:

fit <- auto.arima(tsx)
plot(forecast(fit))

Як додаток до javlacalle і моя відповідь нижче: я впровадив їх тим часом у пакет imputeTS. Ця функція називається na.kalman і робить згладжування Кальмана на державно-просторовій формі моделі ARIMA
stats0007

Відповіді:


25

По-перше, майте на увазі, що forecastобчислюєте вибіркові прогнози, але вас цікавлять спостереження у вибірці.

Фільтр Kalman обробляє відсутні значення. Таким чином, ви можете взяти форму простору стану моделі ARIMA з результатів, повернутих forecast::auto.arimaабо stats::arimaпередати їх KalmanRun.

Редагувати (виправити в коді на основі відповіді stats0007)

У попередній версії я взяв стовпчик відфільтрованих станів, що стосується спостережуваного ряду, однак я повинен використовувати всю матрицю і виконувати відповідну матричну операцію рівняння спостереження, . (Спасибі @ stats0007 за коментарі.) Нижче я відповідно оновлюю код та малюнок.ут=Zαт

Я використовую 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, дуже дякую за допомогу. Чи можу я запитати, чи є якась умова для часового ряду чи це може застосовуватися до будь-якого? Чи можете ви пояснити трохи цих командних рядків? tmp <- який (відповідна Z == 1) id <- ifelse (довжина (tmp) == 1, tmp [1], tmp [2])могел
користувач3730957

Я ще раз перевірив, як makeARIMAвизначаються матриці форми простору стану, і я би сказав, що стовпчик, взятий idправильним, є правильним. Вектор у рівнянні спостереження визначається makeARIMAяк:, Z <- c(1, rep.int(0, r - 1L), Delta)де Deltaвектор, що містить коефіцієнти розрізного фільтра. Якщо немає фільтра розрізнення (тобто моделі ARMA, length(tmp)==1), він idповинен бути 1; в іншому випадку перший стовпець пов'язаний з диференційованим рядом, тоді як наступний елемент при Zприйнятті значення 1 пов'язаний з , індексом, який слід прийняти. ут-1
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:

Thx для вашого допису, дуже цікаво!

У мене є два питання до вашого рішення, сподіваюся, ви можете мені допомогти:

  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)

    Моє рішення неправильне? Або вони обоє в порядку? Чи можете ви пояснити мені далі?


Я рекомендую розміщувати другу частину вашої відповіді як коментар до публікації @ Javlacalle, а не як власну відповідь.
Патрік Куломбе

спробував ... але там сказано, що я маю 50 репутацій, щоб коментувати
stats0007
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.