Eksik değerleri ima etmek için auto.arima nasıl kullanılır


12

Birçok eksik değeri olan bir hayvanat bahçesi serisi var. auto.arimaBu eksik değerleri etkileyebilecek olan okudum mu? Biri bana nasıl yapılacağını öğretebilir mi? çok teşekkürler!

Ben denedim ama başarılı olamadı:

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

Javlacalle ve aşağıdaki cevabımın yanı sıra: Bunları imputeTS paketinde uyguladım. Bu fonksiyon na.kalman olarak adlandırılır ve Kalman bir ARIMA modelinin durum uzayı biçimini yumuşatır
stats0007

Yanıtlar:


25

İlk olarak, forecastörnek dışı tahminleri hesapladığını unutmayın, ancak örnek içi gözlemlerle ilgileniyorsunuz.

Kalman filtresi eksik değerleri işler. Böylece ARIMA modelinin durum uzayı biçimini döndürülen çıktıdan alabilir forecast::auto.arimaya stats::arimada adresine aktarabilirsiniz KalmanRun.

Düzenle (istatistiklere göre cevaba göre kodu düzeltin0007)

Önceki bir versiyonda, gözlemlenen serilerle ilgili filtrelenmiş durumların sütununu aldım, ancak tüm matrisi kullanmalı ve gözlem denkleminin karşılık gelen matris işlemini yapmalıyım, yt=Zαt. (Yorumlar için @ stats0007 sayesinde.) Aşağıda kodu güncelleyip buna göre çizim yapıyorum.

Bunun tsyerine bir örnek serisi olarak bir nesne kullanın zoo, ancak aynı olmalıdır:

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

Sonucu çizebilirsiniz (tüm seri için ve tüm yıl boyunca numunenin ortasında eksik gözlemlerle):

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))

orijinal serilerin ve eksik gözlemlere yansıtılan değerlerin çizimi

Aynı örneği Kalman filtresi yerine Kalman daha pürüzsüz kullanarak tekrarlayabilirsiniz. Değiştirmeniz gereken tek şey şu satırlar:

kr <- KalmanSmooth(x, fit$model)
y[i] <- kr$smooth[i,]

Kalman filtresi aracılığıyla eksik gözlemlerle başa çıkmak bazen serinin ekstrapolasyonu olarak yorumlanır; Kalman daha pürüzsüz kullanıldığında, eksik gözlemlerin gözlemlenen seride enterpolasyon ile doldurulduğu söylenir.


Merhaba Javlacalle, yardımınız için çok teşekkür ederim. Zaman serileri için herhangi bir koşul olup olmadığını sorabilir miyim? Bu komut satırları hakkında biraz bilgi verebilir misiniz? tmp <- hangi (uygunmÖdelZ == 1) id <- ifelse (uzunluk (tmp) == 1, tmp [1], tmp [2])
user3730957

makeARIMADurum uzay formunun matrislerini nasıl tanımladığını tekrar kontrol ettim ve alınan sütunun iddoğru olduğunu söyleyebilirim . Gözlem denklemindeki vektör şu şekilde tanımlanır makeARIMA: Z <- c(1, rep.int(0, r - 1L), Delta)burada Deltafark filtresinin katsayılarını içeren bir vektör. Fark filtresi yoksa (yani bir ARMA modeli length(tmp)==1) id1 olmalıdır; aksi takdirde ilk sütun farklılaştırılmış serilerle, Z1 değerini alarak sonraki öğe iseyt-1, alınması gereken dizin.
javlacalle

1
@ user3730957 Cevabımı dizine ekleme ile bu sorunu gidererek güncelledim.
javlacalle

2

İşte benim çözümüm:

# 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:

Gönderiniz için teşekkürler, çok ilginç!

Çözümünüzle ilgili iki sorum var, umarım bana yardımcı olabilirsiniz:

  1. Neden KalmanSmooth yerine KalmanRun kullanıyorsunuz? Okudum KalmanRun ekstrapolasyon olarak kabul edilirken, pürüzsüz tahmin olurdu.

  2. Ben de kimliğini alamadım. Neden .Z içindeki tüm bileşenleri kullanmıyorsunuz? Örneğin .Z, 1, 0,0,0,0,1, -1 -> 7 değerleri verir. Bu .smooth (KalmanRun eyaletleri için) bana 7 sütun verir Anladığım kadarıyla 1 veya -1 olan sütunlar modele girer.

    Diyelim ki AirPass'te 5 numaralı satır eksik. Sonra böyle 5. satırın toplamını alacağım: Sütun 1'den değer ekleyeceğim (Z 1 verdiğinden), 2-4 sütunu eklemeyeceğim (Z 0 dediği için), Sütun 5 ekleyeceğim ve sütun 7'nin negatif değerini ekleyin (çünkü Z, -1 diyor)

    Çözümüm yanlış mı? Yoksa ikisi de iyi mi? Bana biraz daha açıklayabilir misin?


Cevabınızın ikinci kısmını kendi cevabınız yerine @ Javlacalle'nin yayınına yorum olarak göndermenizi tavsiye ederim.
Patrick Coulombe

çalıştı ... ama yorum yapmak için 50 üne sahip olmalıyım diyor
stats0007
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.