Answers:
首先,请注意,它会forecast
计算样本外预测,但您对样本内观察感兴趣。
卡尔曼滤波器处理缺失值。因此,您可以从forecast::auto.arima
或返回的输出中采用ARIMA模型的状态空间形式,stats::arima
并将其传递给KalmanRun
。
编辑 (根据stats0007的答案修复代码)
在以前的版本中,我采用了与观察到的序列相关的滤波状态列,但是我应该使用整个矩阵,并对观察方程进行相应的矩阵运算。(感谢@ 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,]
通过卡尔曼滤波器处理丢失的观测值有时被解释为该系列的外推法;当使用卡尔曼平滑器时,据称缺失的观测值通过观测序列中的插值来填补。
makeARIMA
定义状态空间形式的矩阵,我会说by所采用的列id
是正确的。观察方程式中的向量定义makeARIMA
为:Z <- c(1, rep.int(0, r - 1L), Delta)
,其中Delta
是一个包含差分滤波器系数的向量。如果没有差异过滤器(例如ARMA模型length(tmp)==1
),id
则应为1;否则为1。否则,第一列与差分序列有关,而Z
取值为1 的下一个元素与(应采用的索引)有关。
这是我的解决方案:
# 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为您的帖子,非常有趣!
对于您的解决方案,我有两个问题,希望您能为我提供帮助:
为什么使用KalmanRun代替KalmanSmooth?我读过KalmanRun被认为是外推法,而平滑法则是估计值。
我也没有得到您的身份证件。为什么不使用.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)
我的解决方案错了吗?或者他们都还好吗?您能否进一步向我解释?