Análise de Séries Temporais com ACF, PACF e o Teste ADF no Python

Na modelagem de séries temporais, ferramentas como a Função de Autocorrelação (ACF) e a Função de Autocorrelação Parcial (PACF) são fundamentais, especialmente na construção de modelos ARIMA. Complementarmente, o Teste de Dickey-Fuller Aumentado (ADF) é crucial para verificar a estacionariedade dos dados.

Função de Autocorrelação (ACF)

A ACF mede a correlação entre uma observação em um determinado ponto no tempo (Yt) e as observações em pontos anteriores (Yt-k), sem remover a influência das observações intermediárias. Em outras palavras, ela quantifica a relação linear entre uma série e suas versões defasadas. Por exemplo, a ACF para uma defasagem de 1 (ACF(1)) mostra a correlação entre o valor atual e o valor do período imediatamente anterior. Essa medida inclui tanto os efeitos diretos quanto os indiretos das defasagens.

Função de Autocorrelação Parcial (PACF)

Ao contrário da ACF, a PACF mede a correlação direta entre uma observação em Yt e uma observação em Yt-k, removendo o impacto das defasagens intermediárias (Yt-1, Yt-2, ..., Yt-k+1). Pense nela como a correlação "pura" ou "direta" entre a observação atual e uma defasagem específica. Por exemplo, a PACF para uma defasagem de 2 (PACF(2)) indica a correlação entre Yt e Yt-2, após remover a influência de Yt-1. É uma ferramenta poderosa para identificar a ordem do componente autorregressivo (AR) em um modelo.

Implementação com statsmodels

A biblioteca statsmodels.tsa.stattools oferece funções para calcular ACF e PACF:

  • statsmodels.tsa.stattools.acf(data, nlags=None, alpha=None, ...)
    • data: A série temporal de entrada (array NumPy ou Pandas Series).
    • nlags: O número máximo de defasagens a serem calculadas. Se omitido, um valor padrão é usado.
    • alpha: Se especificado (e.g., 0.05), retorna os intervalos de confiança para os coeficientes.
  • statsmodels.tsa.stattools.pacf(data, nlags=None, alpha=None, method='ywunbiased', ...)
    • data, nlags, alpha: Similar à função acf.
    • method: O algoritmo para calcular a PACF. Opções comuns incluem 'yw' (Yule-Walker), 'ols' (Regressão de Mínimos Quadrados Ordinários) ou 'ld' (Levinson-Durbin). O método Yule-Walker é frequentemente uma boa escolha.

Para o diagnóstico de modelos AR e MA:

  • Para modelos MA(q): A ACF geralmente "corta" (fica próxima de zero) após a defasagem q, enquanto a PACF decai gradualmente.
  • Para modelos AR(p): A PACF geralmente "corta" após a defasagem p, enquanto a ACF decai gradualmente.

A seguir, um exemplo de como gerar e plotar estas funções para uma série simulada:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima_process import ArmaProcess

# 1. Simular um processo AR(1): Y_t = 0.7 * Y_{t-1} + Epsilon_t
ar_coefs = np.array([1, -0.7]) # statsmodels usa sinais invertidos para AR
ma_coefs = np.array([1]) # Nenhum componente MA
series_data = ArmaProcess(ar_coefs, ma_coefs).generate_sample(nsample=500)

# 2. Visualizar a série temporal
plt.figure(figsize=(10, 5))
plt.plot(series_data)
plt.title('Série Temporal Simulada: Processo AR(1)')
plt.grid(True)
plt.show()

# 3. Plotar ACF e PACF
fig, (plot1, plot2) = plt.subplots(2, 1, figsize=(12, 10))

# Plotar ACF: Espera-se um decaimento gradual para um processo AR(1)
plot_acf(series_data, lags=30, alpha=0.05, ax=plot1)
plot1.set_title('Função de Autocorrelação (ACF)')
plot1.grid(True)

# Plotar PACF: Espera-se um corte abrupto após a defasagem 1 para um processo AR(1)
plot_pacf(series_data, lags=30, alpha=0.05, ax=plot2, method='ywm')
plot2.set_title('Função de Autocorrelação Parcial (PACF)')
plot2.grid(True)

plt.tight_layout()
plt.show()

No contexto de ACF/PACF:

  • Decaimento gradual (ou "Tailing Off"): Refere-se a quando os valores da função diminuem gradualmente, mas não se tornam zero estatisticamente significativos após algumas defasagens. Isso sugere uma memória mais longa na série.
  • Corte abrupto (ou "Cutting Off"): Ocorre quando os valores da função se tornam insignificantes (caem dentro do intervalo de confiança) após uma defasagem específica. Isso indica que a influência das defasagens posteriores àquela pode ser desconsiderada.

Teste de Dickey-Fuller Aumentado (ADF)

Antes de aplicar modelos ARIMA, é essencial assegurar que a série temporal seja estacionária. Uma série estacionária possui média, variância e estrutura de autocorrelação constantes ao longo do tempo. O Teste ADF é um método estatístico robusto para verificar a presença de uma raiz unitária, que é um indicativo de não estacionariedade.

Conceitos Fundamentais

  • Raiz Unitária: Se uma série temporal possui uma raiz unitária, ela exibe comportamento de "caminhada aleatória", onde o valor atual é o valor anterior mais um choque aleatório, resultando em uma variância que aumenta com o tempo.
  • Estacionariedade: É uma propriedade crucial para muitos modelos de séries temporais. Uma série estacionária possui características estatísticas estáveis ao longo do tempo, facilitando a modelagem.
  • Hipótese Nula (H₀): A série possui uma raiz unitária (é não estacionária).
  • Hipótese Alternativa (H₁): A série não possui uma raiz unitária (é estacionária).

Função adfuller

A função statsmodels.tsa.stattools.adfuller realiza o teste ADF:

from statsmodels.tsa.stattools import adfuller

# Exemplo de uso:
# result_adf = adfuller(minha_serie_temporal, maxlag=None, regression='c', autolag='AIC')

Parâmetros chave:

  • x: A série temporal a ser testada.
  • maxlag: O número máximo de defasagens a serem incluídas na regressão.
  • regression: Especifica o tipo de regressão:
    • 'c': Inclui apenas um intercepto (padrão).
    • 'ct': Inclui intercepto e uma tendência linear.
    • 'nc': Sem intercepto ou tendência.
  • autolag: Método para selecionar automaticamente o número de defasagens ótimas, como 'AIC' (Critério de Informação de Akaike) ou 'BIC' (Critério de Informação Bayesiano).

Interpretação dos Resultados

A função retorna uma tupla com:

  1. O valor da estatística ADF.
  2. O p-valor.
  3. O número de defasagens utilizadas.
  4. O número de observações usadas.
  5. Valores críticos para diferentes níveis de significância (1%, 5%, 10%).

A decisão é tomada com base no p-valor:

  • Se p-valor < nível de significância (e.g., 0.05): Rejeitamso H₀. A série é estacionária.
  • Caso contrário: Não rejeitamos H₀. A série é não estacionária e pode precisar de diferenciação.
# Exemplo prático do teste ADF
np.random.seed(42)
# Série não estacionária (caminhada aleatória)
random_walk = np.cumsum(np.random.randn(200)) + 50
non_stationary_series = pd.Series(random_walk)

# Série estacionária (ruído branco)
stationary_series = pd.Series(np.random.randn(200))

# Testar a série não estacionária
print("--- Teste ADF para Série Não Estacionária ---")
result_non_stationary = adfuller(non_stationary_series)
print(f"Estatística ADF: {result_non_stationary[0]:.4f}")
print(f"P-valor: {result_non_stationary[1]:.4f}")
if result_non_stationary[1] < 0.05:
    print("Conclusão: Série provavelmente estacionária (rejeita H0)")
else:
    print("Conclusão: Série provavelmente não estacionária (não rejeita H0)")

# Diferenciar a série não estacionária para torná-la estacionária
diff_series = non_stationary_series.diff().dropna()

# Testar a série diferenciada
print("\n--- Teste ADF para Série Diferenciada (Potencialmente Estacionária) ---")
result_diff = adfuller(diff_series)
print(f"Estatística ADF: {result_diff[0]:.4f}")
print(f"P-valor: {result_diff[1]:.4f}")
if result_diff[1] < 0.05:
    print("Conclusão: Série provavelmente estacionária (rejeita H0)")
else:
    print("Conclusão: Série provavelmente não estacionária (não rejeita H0)")

Diferenciação e Reversão da Diferenciação (Inverse Differencing)

O parâmetro d em um modelo ARIMA(p,d,q) representa a ordem de diferenciação necessária para tornar a série estacionária. Após prever valores em uma série diferenciada, é preciso realizar a operação inversa para retornar às previsões na escala original dos dados.

Reversão para Diferenciação de Primeira Ordem

import pandas as pd
import numpy as np

# Exemplo de série original
original_values = pd.Series([100, 105, 108, 115, 120, 128])

# Diferenciação de primeira ordem
diff_order_1 = original_values.diff().dropna()
print("Série Diferenciada (Ordem 1):\n", diff_order_1.values) # [5, 3, 7, 5, 8]

# Supondo uma previsão para o próximo valor diferenciado
predicted_diff_val = 6

# Reverter para obter a previsão na escala original
last_original = original_values.iloc[-1] # Último valor da série original (128)
predicted_original_val = last_original + predicted_diff_val
print(f"Previsão na escala original: {predicted_original_val}") # 128 + 6 = 134

Reversão para Diferenciação de Segunda Ordem

# Exemplo de série para diferenciação de segunda ordem
raw_data = pd.Series([20, 22, 27, 35, 48, 65, 85])

# Primeira diferenciação
first_diff_series = raw_data.diff().dropna() # [2, 5, 8, 13, 17, 20]

# Segunda diferenciação
second_diff_series = first_diff_series.diff().dropna() # [3, 3, 5, 4, 3]

print("Série de 2ª Ordem Diferenciada:\n", second_diff_series.values)

# Supondo uma previsão para o próximo valor da segunda ordem diferenciada
next_predicted_second_diff = 3

# PASSO 1: Reverter da 2ª ordem diferenciada para a 1ª ordem diferenciada
last_first_diff = first_diff_series.iloc[-1] # Último valor da primeira diferenciação (20)
next_predicted_first_diff = last_first_diff + next_predicted_second_diff # 20 + 3 = 23

# PASSO 2: Reverter da 1ª ordem diferenciada para a escala original
last_raw_data = raw_data.iloc[-1] # Último valor da série original (85)
final_predicted_original = last_raw_data + next_predicted_first_diff # 85 + 23 = 108

print(f"Previsão final na escala original: {final_predicted_original}") # 108

Tags: ARIMA ACF PACF ADF Test Time Series

Publicado em 7-21 00:48