如何使用auto.arima插补缺失值


12

我有一个动物园系列,但缺少很多值。我读到auto.arima可以推论这些缺失的值吗?谁能教我该怎么做?非常感谢!

这是我尝试过的,但是没有成功:

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

作为对javlacalle的补充,我的回答如下:我同时在imputeTS包中实现了这些功能。该函数称为na.kalman,并对ARIMA模型的状态空间形式进行Kalman平滑处理
stats0007

Answers:


25

首先,请注意,它会forecast计算样本外预测,但您对样本内观察感兴趣。

卡尔曼滤波器处理缺失值。因此,您可以从forecast::auto.arima或返回的输出中采用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))

原始序列的图和归因于缺失观测值的值

您可以使用Kalman平滑器代替Kalman滤波器来重复同一示例。您需要更改的只是以下几行:

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

通过卡尔曼滤波器处理丢失的观测值有时被解释为该系列的外推法;当使用卡尔曼平滑器时,据称缺失的观测值通过观测序列中的插值来填补。


您好Javlacalle,非常感谢您的帮助。请问时间序列是否有条件或可以适用?您能解释一下这些命令行吗?tmp <-其中(拟合 Z == 1)id <-ifelse(length(tmp)== 1,tmp [1],tmp [2])model
user373095714年

我再次检查了如何makeARIMA定义状态空间形式的矩阵,我会说by所采用的列id是正确的。观察方程式中的向量定义makeARIMA为:Z <- c(1, rep.int(0, r - 1L), Delta),其中Delta是一个包含差分滤波器系数的向量。如果没有差异过滤器(例如ARMA模型length(tmp)==1),id则应为1;否则为1。否则,第一列与差分序列有关,而Z取值为1 的下一个元素与(应采用的索引)有关。yt1
javlacalle 2014年

1
@ user3730957我已经更新了我的答案,使用索引解决了这个问题。
javlacalle '16

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的alle列放入模型中。

    假设AirPass中缺少第5行。然后,我将这样计算第5行的总和:我将从第1列中添加值(因为Z为1),我不会添加第2-4列(因为Z为0),我将添加第5列,添加第7列的负值(因为Z表示-1)

    我的解决方案错了吗?或者他们都还好吗?您能否进一步向我解释?


我建议将您答案的第二部分作为对@Javlacalle帖子的评论,而不是您自己的答案。
Patrick Coulombe

尝试过...但是它说我必须有50个声誉才能发表评论
stats0007 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.