Objetivo deste notebook é analisar a série temporal ‘Ocupação’ Dataset: Pessoas de 14 anos ou mais de idade, ocupadas na semana de referência (milhares) 2022 - 2023 Fonte: https://sidra.ibge.gov.br/home/pnadcm/brasil
Imports
Code
import seaborn as snsimport matplotlib.pyplot as pltimport pandas as pdfrom statsmodels.tsa.stattools import adfuller from statsmodels.tsa.seasonal import seasonal_decomposefrom statsmodels.tsa.statespace.sarimax import SARIMAXfrom pandas.tseries.offsets import DateOffsetfrom statsmodels.graphics.tsaplots import plot_acf, plot_pacffrom statsmodels.tsa.arima.model import ARIMA
Tratamento dos dados
Code
# Lendo os dados já tratados.df = pd.read_csv('../data/pessoas_ocupadas_2022-2023.csv')df = df.Tdf = df.rename(columns={0:"pessoas_trabalhando"})df.index = pd.to_datetime(df.index)df.index = df.index.to_period("M")df.pessoas_trabalhando = pd.to_numeric(df.pessoas_trabalhando)index = df.index.to_timestamp()
Code
fig, ax = plt.subplots(figsize=(15, 6))# Plot the dataax.plot(index, df['pessoas_trabalhando'], marker='o', linestyle='-', color='green')# Set title and labelsax.set_title('Pessoas trabalhando ao longo de 2022-2023')ax.set_xlabel('Anos')ax.set_ylabel('Pessoas trabalhando')# Enable gridax.grid(True)# Show plotplt.show()
Este é o gráfico da série temporal de dados original, mostra as flutuações ao longo do tempo. Podemos observar que existem variações periódicas e alguns picos e vales ao longo da série.
Tendência
O gráfico de tendência mostra como a série temporal evolui ao longo do tempo, excluindo a sazonalidade e o ruído. Há uma tendência geral de aumento, indicando que há um crescimento ou uma tendência ascendente na série ao longo do período observado. Exatamente como havíamos pontuado antes!
Sazonalidade
Este componente revela padrões que se repetem em intervalos regulares. O gráfico da sazonalidade não mostra um padrão claro e repetitivo, sugerindo que a sazonalidade pode não ser um fator significativo na série temporal ou que o período de sazonalidade pode não estar bem capturado.
Resíduos
Este gráfico mostra o que resta da série temporal após a remoção da tendência e da sazonalidade. Os resíduos representam a flutuação aleatória que não pode ser explicada pelos modelos de tendência ou sazonalidade. O ideal é que os resíduos pareçam ser ruído branco, ou seja, sem padrões discerníveis, o que indicaria que a tendência e a sazonalidade foram bem capturadas nos outros componentes.
Teste ADF para ver se esta série temporal é estacionária
Code
# Diferenciaçãodf['diff_pessoas_trabalhando'] = df['pessoas_trabalhando'].diff().fillna(0)# Realizando o teste ADF na série temporal 'diff_net_revenue'adf_test_result_diff = adfuller(df['diff_pessoas_trabalhando'])# Criando um DataFrame para exibir os resultados do teste de forma mais clara# Incluindo os valores críticosadf_test_result_diff = pd.DataFrame({'Item': ['Test Statistic', 'p-value', '#Lags Used', 'Number of Observations Used','Critical Value (1%)', 'Critical Value (5%)', 'Critical Value (10%)' ],'Value': [ adf_test_result_diff[0], # Test statistic adf_test_result_diff[1], # p-value adf_test_result_diff[2], # #Lags Used adf_test_result_diff[3], # Number of Observations Used adf_test_result_diff[4]['1%'], # Critical Value for 1% adf_test_result_diff[4]['5%'], # Critical Value for 5% adf_test_result_diff[4]['10%'] # Critical Value for 10% ]})adf_test_result_diff
Item
Value
0
Test Statistic
-2.801834
1
p-value
0.058012
2
#Lags Used
9.000000
3
Number of Observations Used
14.000000
4
Critical Value (1%)
-4.012034
5
Critical Value (5%)
-3.104184
6
Critical Value (10%)
-2.690987
p-value > 0.05 ; logo, não é estacionária
Além disso: Test Statistic > CV(10%) > CV(5%) > CV(1%). Logo, a hipótese nula pode ser rejeitada com um nível de confiança de <=80%
Como a série possui sazonalidade, vou usar SARIMAX como modelo de predição.
Code
# Plotando ACF e PACF para descobrir os melhores hiperparâmetros do SARIMAXfig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))# Autocorrelaçãoplot_acf(df['diff_pessoas_trabalhando'], ax=ax1)# Autocorrelação Parcialplot_pacf(df['diff_pessoas_trabalhando'], ax=ax2, method='ywm')plt.show()
Code
p =1# ordem do componente autoregressivod =1# ordem de diferenciaçãoq =1# ordem do componente de média móvel# Modelo SARIMAXmodel = SARIMAX(df['pessoas_trabalhando'], order=(p, d, q), seasonal_order=(1, 1, 0, 12))model_fit = model.fit(disp=False)
/home/liputer/.local/lib/python3.10/site-packages/statsmodels/tsa/statespace/sarimax.py:866: UserWarning: Too few observations to estimate starting parameters for seasonal ARMA. All parameters except for variances will be set to zeros.
warn('Too few observations to estimate starting parameters%s.'
Fazendo a previsão com SARIMAX
Code
# Previsões das datas futurasfuture_dates = [index[-1] + DateOffset(weeks=x) for x inrange(1, 27)]# Previsões dos valoresforecast_object = model_fit.get_forecast(steps=26)# Intervalo de confiançaconfianca = forecast_object.conf_int()# Criando dataset com os valores futuros colhidosforecast_df = pd.DataFrame({'date': future_dates,'predicted_pessoas_trabalhando': forecast_object.predicted_mean,'lower_confidence': confianca.iloc[:, 0],'upper_confidence': confianca.iloc[:, 1]})
Code
# Plotando os dados históricos e as previsõesplt.figure(figsize=(15, 6))plt.plot(index, df['pessoas_trabalhando'], label='Histórico', color='blue')plt.plot(forecast_df['date'], forecast_df['predicted_pessoas_trabalhando'], label='Predições', color='red', linestyle='--')# Adicionando intervalo de confiançaplt.fill_between(forecast_df['date'],forecast_df['lower_confidence'],forecast_df['upper_confidence'], color='pink', alpha=0.8)plt.title('Previsão')plt.xlabel('Datas')plt.ylabel('Receita')plt.legend()plt.show()
Conclusão
Mesmo que essa série temporal tenha sazonalidade, a previsão com SARIMAX não teve resultados agradáveis.