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#

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
  • 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
  • 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
  • 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
  • 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
  • Mecanismo de plotagem direta

dp = df_add.plot()
../_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