Dataviz Code Session: Séries Temporais
Contents
16. Dataviz Code Session: Séries Temporais#
16.1. Objetivos da DCS#
Aplicar técnicas de dataviz para plotagem e manipulação de séries temporais;
Manipular séries temporais (STs) relativas a dados de repasses da arrecadação federal efetivados pela Secretaria Especial da Receita Federal do Brasil a outras entidades e fundos;
Produzir representações visuais de STs e suas componentes fundamentais (tendência, sazonalidade e ruído);
16.2. Ferramentas utilizadas#
Módulos Python
pandas
sys
matplotlib
seaborn
statsmodels
numpy
16.3. Aplicação do modelo referencial#
Vide Capítulo 3.
from matplotlib.patches import Patch
from statsmodels.tsa.seasonal import seasonal_decompose
import pandas as pd, matplotlib.pyplot as plt, seaborn as sb, numpy as np
import sys; sys.path.insert(1,'../dcs')
import dcs27
plt.style.use('../etc/gcpeixoto-datavis.mplstyle') # style sheet
16.4. Dados de entrada pré-processados#
# carrega dados da RFB
df = dcs27.load_data(keep_orig=False,show_links=False)
Extracting data from Receita Federal do Brasil...
Data loaded successfully.
df
Mês | Ano | Entidade | Total Repassado | |
---|---|---|---|---|
0 | jan | 2015 | FNDE | 2.604078e+09 |
1 | jan | 2015 | INCRA | 1.814560e+08 |
2 | jan | 2015 | SENAI | 2.191193e+08 |
3 | jan | 2015 | SESI | 3.133701e+08 |
4 | jan | 2015 | SENAC | 3.340052e+08 |
... | ... | ... | ... | ... |
2001 | out | 2024 | SENAT | 5.100038e+07 |
2002 | out | 2024 | SESCOOP | 5.394943e+07 |
2003 | out | 2024 | SDR | 1.334507e+05 |
2004 | out | 2024 | APEX-BR | 6.206777e+07 |
2005 | out | 2024 | ABDI | 9.939801e+06 |
2006 rows × 4 columns
16.4.1. Processamento adicional#
Listagem de entidades disponíveis para análise
# lista de entidades disponíveis
df['Entidade'].unique()
array(['FNDE', 'INCRA', 'SENAI', 'SESI', 'SENAC', 'SESC', 'SEBRAE',
'EMBRATUR', 'DPC', 'ANAC', 'SENAR', 'SEST', 'SENAT', 'SESCOOP',
'SDR', 'APEX-BR', 'ABDI'], dtype=object)
Escolha de entidade e filtragem
entity = 'INCRA'
df_e = df[df['Entidade'] == entity].reset_index(drop=True)
16.5. Mapeamento#
Criação de string representativa de temporalidade;
Conversão de string para objeto
datetime
;Plotagem direta de curvas em eixos cartesianos;
Frequência mensal;
Frequência anual;
Montagem de string representativa da temporalidade (período)
df_e['Período'] = pd.Series([v['Mês'] + '/' + v['Ano'] for i,v in df_e.iterrows()])
df_e
Mês | Ano | Entidade | Total Repassado | Período | |
---|---|---|---|---|---|
0 | jan | 2015 | INCRA | 1.814560e+08 | jan/2015 |
1 | fev | 2015 | INCRA | 1.062026e+08 | fev/2015 |
2 | mar | 2015 | INCRA | 1.044018e+08 | mar/2015 |
3 | abr | 2015 | INCRA | 1.042058e+08 | abr/2015 |
4 | mai | 2015 | INCRA | 1.026660e+08 | mai/2015 |
... | ... | ... | ... | ... | ... |
113 | jun | 2024 | INCRA | 2.094306e+08 | jun/2024 |
114 | jul | 2024 | INCRA | 2.275669e+08 | jul/2024 |
115 | ago | 2024 | INCRA | 2.239196e+08 | ago/2024 |
116 | set | 2024 | INCRA | 2.471706e+08 | set/2024 |
117 | out | 2024 | INCRA | 2.151508e+08 | out/2024 |
118 rows × 5 columns
Plotagem simples
Eixo emaranhado;
Falta de controle de espaçamento;
fig, ax = plt.subplots(figsize=(12,3),constrained_layout=True)
s1 = sb.lineplot(data=df_e,x='Período',y='Total Repassado',
#errorbar=None,
ax=ax)
ax.tick_params(axis='x', rotation=90, labelsize = 8)
![../_images/27-dcs-serietemporal_18_0.png](../_images/27-dcs-serietemporal_18_0.png)
Transformação para objeto
datetime
# ver função 'map_my' auxiliar
df_e['Período'] = pd.to_datetime(df_e['Período'].apply(lambda x: dcs27.map_my(x)))
16.6. Visualização#
16.6.1. Iterando em RVs primárias#
Plotagem com eixo automaticamente controlado
Exploração de
seaborn.lineplot
Quadro de STs (frequência mensal)
fig, ax = plt.subplots(figsize=(12,3),constrained_layout=True)
s1 = sb.lineplot(data=df_e,
x='Período', y='Total Repassado',
color=plt.rcParams['axes.edgecolor'], # cor do estilo customizado
#errorbar=None,
ax=ax)
ax.set_title(f'Série histórica: repasse RFB para {entity}',fontsize=14);
![../_images/27-dcs-serietemporal_23_0.png](../_images/27-dcs-serietemporal_23_0.png)
Plotagem de séries por frequência mensal
df_em = df_e.set_index('Ano')
df_em
Mês | Entidade | Total Repassado | Período | |
---|---|---|---|---|
Ano | ||||
2015 | jan | INCRA | 1.814560e+08 | 2015-01-01 |
2015 | fev | INCRA | 1.062026e+08 | 2015-02-01 |
2015 | mar | INCRA | 1.044018e+08 | 2015-03-01 |
2015 | abr | INCRA | 1.042058e+08 | 2015-04-01 |
2015 | mai | INCRA | 1.026660e+08 | 2015-05-01 |
... | ... | ... | ... | ... |
2024 | jun | INCRA | 2.094306e+08 | 2024-06-01 |
2024 | jul | INCRA | 2.275669e+08 | 2024-07-01 |
2024 | ago | INCRA | 2.239196e+08 | 2024-08-01 |
2024 | set | INCRA | 2.471706e+08 | 2024-09-01 |
2024 | out | INCRA | 2.151508e+08 | 2024-10-01 |
118 rows × 4 columns
fig, ax = plt.subplots(figsize=(12,3),constrained_layout=True)
# paleta de cores
pal = sb.color_palette('Oranges',len(df_em.index.unique()))
#
for i,y in enumerate(df_em.index.unique()):
# sy = sb.lineplot(data=df_em,
# x=df_em.loc[y]['Mês'],
# y=df_em.loc[y]['Total Repassado'],
# marker='o',
# color=pal[i],
# #errorbar=None,
# #ax=ax,
# label=y)
plt.plot(df_em.loc[y]['Mês'],df_em.loc[y]['Total Repassado'],'o-',color=pal[i],label=y)
ax.legend(loc='best', bbox_to_anchor=(1.1,1.1), title='Ano')
ax.grid(axis='x')
ax.set_title(f'Série histórica (mensal): repasse RFB para {entity}',fontsize=14);
![../_images/27-dcs-serietemporal_27_0.png](../_images/27-dcs-serietemporal_27_0.png)
Identificação de componentes
Nota 1: STs podem ou não apresentar padrões. Padrões comuns são: i) tendência (comportamento monotônico); ii) sazonalidade (comportamento alternado devido a fatores sazonais); iii) híbrido (comportamento que apresenta tendências e efeitos sazonais combinados).
Nota 2: uma ST pode ser descrita por uma soma ou um produto de componentes:
statsmodels.tsa.seasonal_decompose
reproduz a ST observada e outras 3 componentes.
ST aditiva: valor = tendência + ciclo + sazonalidade + irregularidade
# componentes por modelo aditivo
df_add = seasonal_decompose(x=df_em.set_index('Período')['Total Repassado'],
model='additive',
extrapolate_trend='freq')
# figura
fig, ax = plt.subplots(4,1,figsize=(6,4),sharex=True,constrained_layout=True)
# plotagem das componentes
ax[0].plot(df_add.observed,color=pal[2])
ax[1].plot(df_add.trend,color=pal[4])
ax[2].plot(df_add.seasonal,color=pal[6])
ax[3].plot(df_add.resid,'o',color=pal[8])
# decoração
ax[0].set_title('Série temporal observada',fontsize=10)
ax[1].set_title('Componente: tendência',fontsize=10)
ax[2].set_title('Componente: sazonalidade',fontsize=10)
ax[3].set_title('Componente: irregularidade',fontsize=10)
ax[3].set_xlabel('Período',fontsize=10)
fig.suptitle('Componentes da ST: modelo aditivo');
![../_images/27-dcs-serietemporal_30_0.png](../_images/27-dcs-serietemporal_30_0.png)
ST multiplicativa: valor = tendência x ciclo x sazonalidade x irregularidade
# componentes por modelo multiplicativo
df_mul = seasonal_decompose(x=df_em.set_index('Período')['Total Repassado'],
model='multiplicative',
extrapolate_trend='freq')
# figura
fig, ax = plt.subplots(4,1,figsize=(6,4),sharex=True,constrained_layout=True)
# plotagem das componentes
ax[0].plot(df_mul.observed,color=pal[2])
ax[1].plot(df_mul.trend,color=pal[4])
ax[2].plot(df_mul.seasonal,color=pal[6])
ax[3].plot(df_mul.resid,'o',color=pal[8])
# decoração
ax[0].set_title('Série temporal observada',fontsize=10)
ax[1].set_title('Componente: tendência',fontsize=10)
ax[2].set_title('Componente: sazonalidade',fontsize=10)
ax[3].set_title('Componente: irregularidade',fontsize=10)
ax[3].set_xlabel('Período',fontsize=10)
fig.suptitle('Componentes da ST: modelo multiplicativo');
![../_images/27-dcs-serietemporal_32_0.png](../_images/27-dcs-serietemporal_32_0.png)
Mecanismo de plotagem direta
dp = df_add.plot()
![../_images/27-dcs-serietemporal_34_0.png](../_images/27-dcs-serietemporal_34_0.png)
16.7. RV finalística#
Define função para plotar ST(s) específica(s) com alguma decoração.
df['Entidade'].unique()
array(['FNDE', 'INCRA', 'SENAI', 'SESI', 'SENAC', 'SESC', 'SEBRAE',
'EMBRATUR', 'DPC', 'ANAC', 'SENAR', 'SEST', 'SENAT', 'SESCOOP',
'SDR', 'APEX-BR', 'ABDI'], dtype=object)
# entidades do sistema S
S = ['ABDI']
fig, ax = plt.subplots(figsize=(12,3),constrained_layout=True)
# plotagens individuais
for i,s in enumerate(S):
s1 = dcs27.plot_ts_rfb(df,s,ax,pal[i+3]) # função auxiliar
ax.set_title(f'Série histórica: repasses anuais da RFB para entidades do Sistema S',fontsize=14);
![../_images/27-dcs-serietemporal_37_0.png](../_images/27-dcs-serietemporal_37_0.png)