วิธีใช้ auto.arima เพื่อใส่ค่าที่หายไป


12

ฉันมีสวนสัตว์ซีรีส์ที่มีค่าหายไปมากมาย ฉันอ่านที่auto.arimaสามารถระบุค่าที่หายไปเหล่านี้ได้หรือไม่ ทุกคนสามารถสอนฉันถึงวิธีการทำได้หรือไม่? ขอบคุณมาก!

นี่คือสิ่งที่ฉันได้ลอง แต่ไม่ประสบความสำเร็จ:

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

นอกเหนือจาก javlacalle และคำตอบของฉันด้านล่าง: ฉันใช้สิ่งเหล่านี้ในแพ็คเกจ imputeTS ฟังก์ชั่นนี้เรียกว่า na.kalman และทำให้ Kalman ปรับรูปแบบพื้นที่ในแบบจำลอง ARIMA ให้มีความ
ราบรื่น

คำตอบ:


25

ก่อนอื่นให้ระวังว่าforecastคำนวณการคาดการณ์ภายนอกตัวอย่าง แต่คุณสนใจในการสังเกตในตัวอย่าง

ตัวกรองคาลมานจัดการกับค่าที่หายไป ดังนั้นคุณสามารถใช้รูปแบบสภาพพื้นที่ของรูปแบบ ARIMA จากการส่งออกที่ส่งกลับโดยforecast::auto.arimaหรือและผ่านมันไปstats::arimaKalmanRun

แก้ไข (แก้ไขในรหัสตามคำตอบโดย stats0007)

ในรุ่นก่อนหน้าฉันเอาคอลัมน์ของสถานะการกรองที่เกี่ยวข้องกับชุดข้อมูลที่สังเกต แต่ฉันควรใช้เมทริกซ์ทั้งหมดและดำเนินการเมทริกซ์ที่สอดคล้องกันของสมการสังเกต Yเสื้อ=Zαเสื้อ. (ขอบคุณที่ @ stats0007 สำหรับความคิดเห็น) ด้านล่างฉันอัปเดตรหัสและพล็อตตาม

ฉันใช้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))

พล็อตของซีรี่ส์ดั้งเดิมและค่าที่แสดงถึงการสังเกตที่ขาดหายไป

คุณสามารถทำซ้ำตัวอย่างเดียวกันโดยใช้ Kalman นุ่มนวลแทนตัวกรอง Kalman สิ่งที่คุณต้องเปลี่ยนคือบรรทัดเหล่านี้:

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

การจัดการกับข้อสังเกตที่ขาดหายไปโดยวิธีการของตัวกรองคาลมานบางครั้งก็ตีความว่าเป็นการคาดการณ์ของซีรีส์; เมื่อใช้คาลมานอย่างราบรื่นการสังเกตที่หายไปจะถูกเติมด้วยการสอดแทรกในซีรีย์ที่สังเกต


สวัสดี Javlacalle ขอบคุณมากสำหรับความช่วยเหลือของคุณ ฉันขอถามได้ว่ามีเงื่อนไขใด ๆ สำหรับช่วงเวลาหรือไม่ คุณช่วยอธิบายเล็กน้อยเกี่ยวกับบรรทัดคำสั่งเหล่านี้ได้ไหม tmp <- อันไหน (พอดีม.โอdอีล.Z == 1) id <- ifelse (length (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 จะเกี่ยวข้องกับYเสื้อ-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:

ขอบคุณสำหรับการโพสต์ของคุณน่าสนใจมาก!

ฉันมีคำถามสองข้อสำหรับวิธีการแก้ปัญหาของคุณหวังว่าคุณสามารถช่วยฉัน:

  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 แทนที่จะเป็นคำตอบของคุณเอง
Patrick Coulombe

พยายาม ... แต่มันบอกว่าฉันจะต้องมี 50 ชื่อเสียงที่จะแสดงความคิดเห็น
stats0007
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.