Como usar o auto.arima para atribuir valores ausentes

12

Eu tenho uma série de zoológicos com muitos valores ausentes. Eu li que auto.arimapode imputar esses valores ausentes? Alguém pode me ensinar como fazer isso? Muito obrigado!

Isto é o que eu tentei, mas sem sucesso:

fit <- auto.arima(tsx)
plot(forecast(fit))
user3730957
fonte
Como um complemento para javlacalle e minha resposta abaixo: implementei isso enquanto isso no pacote imputeTS. A função é chamada na.kalman e não Kalman suavização na forma de espaço de estados de um modelo ARIMA
stats0007

Respostas:

25

Primeiro, saiba que forecastcalcula previsões fora da amostra, mas você está interessado em observações dentro da amostra.

O filtro Kalman lida com os valores ausentes. Assim, você pode pegar a forma de espaço de estado do modelo ARIMA a partir da saída retornada por forecast::auto.arimaou stats::arimae passá-la para KalmanRun.

Editar (corrija o código com base na resposta do stats0007)

Em uma versão anterior, peguei a coluna dos estados filtrados relacionados às séries observadas, no entanto, devo usar toda a matriz e fazer a operação correspondente da matriz da equação de observação, . (Obrigado a @ stats0007 pelos comentários.) Abaixo, atualizo o código e plogo de acordo.yt=Zαt

Eu uso um tsobjeto como uma série de exemplos em vez de zoo, mas deve ser o mesmo:

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

Você pode plotar o resultado (para toda a série e para o ano inteiro com observações ausentes no meio da amostra):

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

traçado da série original e os valores atribuídos a observações ausentes

Você pode repetir o mesmo exemplo usando o Kalman mais suave em vez do filtro Kalman. Tudo que você precisa alterar são as seguintes linhas:

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

Lidar com observações ausentes por meio do filtro de Kalman às vezes é interpretado como extrapolação da série; quando o Kalman mais suave é usado, as observações ausentes são preenchidas por interpolação nas séries observadas.

javlacalle
fonte
Olá Javlacalle, muito obrigado pela sua ajuda. Posso perguntar se existe alguma condição para a série cronológica ou se ela pode ser aplicada? Você poderia explicar um pouco sobre essas linhas de comando? tmp <- que ( ajuste Z == 1) id <- ifelse (length (tmp) == 1, tmp [1], tmp [2])model
user3730957
Eu verifiquei novamente como makeARIMAdefine as matrizes do formulário do espaço de estados e eu diria que a coluna obtida idestá correta. O vetor na equação de observação é definido makeARIMAcomo:, Z <- c(1, rep.int(0, r - 1L), Delta)onde Deltaé um vetor que contém os coeficientes do filtro diferencial. Se não houver filtro diferencial (isto é, um modelo ARMA length(tmp)==1) , então iddeve ser 1; caso contrário, a primeira coluna está relacionada às séries diferenciadas, enquanto o próximo elemento ao Zassumir o valor 1 está relacionado a , o índice que deve ser utilizado. yt1
Javlacalle
11
@ user3730957 Atualizei minha resposta corrigindo esse problema com a indexação.
Javlacalle #
2

Aqui seria a minha solução:

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

Obrigado pelo seu post, muito interessante!

Tenho duas perguntas para sua solução, espero que você possa me ajudar:

  1. Por que você usa o KalmanRun em vez do KalmanSmooth? Eu li que KalmanRun é considerado extrapolação, enquanto suave seria uma estimativa.

  2. Eu também não entendo sua parte de identificação. Por que você não usa todos os componentes em .Z? Quero dizer, por exemplo .Z fornece 1, 0,0,0,0,1, -1 -> 7 valores. Isso significa que .smooth (no seu caso para os estados do KalmanRun) me fornece 7 colunas. Pelo que entendi, todas as colunas que são 1 ou -1 vão para o modelo.

    Digamos que a linha número 5 esteja ausente no AirPass. Então eu pegaria a soma da linha 5 assim: acrescentaria valor da coluna 1 (porque Z deu 1), não acrescentaria a coluna 2-4 (porque Z diz 0), acrescentaria a coluna 5 e acrescentaria adicione o valor negativo da coluna 7 (porque Z diz -1)

    Minha solução está errada? Ou ambos estão bem? Talvez você possa me explicar mais?

stats0007
fonte
Eu recomendaria postar a segunda parte da sua resposta como comentários na postagem de @ Javlacalle, e não dentro da sua própria resposta.
Patrick Coulombe
tentou ... mas ele diz que eu tenho que ter 50 reputação ao comentário
stats0007