Pandas Time Series (Pt. I/II)

Como extrair conhecimento através de séries temporais.

Nesse artigo, geraremos gráficos utilizando o matplotlib e seaborn. Aprenderemos técnicas como decomposição e correlação de séries temporais, entendendo como interpretar esses gráficos.

Na parte dois, veremos como normalizar uma série temporal, encontrar o que é tendência, sazonalidade e ruído, normalizando e minimizando essas frequências com o uso de médias móveis.

Análise de vendas da Anello & Cia.

Vamos iniciar nosso estudo a respeito de Time Series. Para iniciar nosso estudo, precisaremos carregar os dados. Para conseguirmos ler um arquivo csv, precisaremos importar o Pandas:

import pandas as pd

Vamos ler o arquivo ‘anello_e_cia.csv’ com Pandas e carregá-lo diretamente no objeto anello que manipularemos ao longo de toda nossa análise.

anello = pd.read_csv('anello_e_cia.csv')
anello.head()
DataFrame anello

Eles serão abertos e terão duas colunas: uma coluna referente a alguns meses, e outra com a quantidade de vendas relacionada a esses meses.

Antes de criar um gráfico, faremos uma análise desses dados, pois ainda não sabemos quantas colunas, quantas linhas ou quanto tempo de dados temos.

print('Quantidade de linhas e colunas', anello.shape)
Tendo 24 registros de meses, já podemos supor que são 2 anos de dados.

Também poderemos analisar se há dados nulos, e quantos são eles. Para isso, escreveremos:

print ('Quantidade de dados nulos', anello.isna().sum())

Dessa forma, será exibida o número de dados nulos que temos no mês e o número de nulos nas vendas.

Se quisermos que sejam exibidos os dados nulos no total, independentemente das variáveis, adicionamos mais um .sum:

print ('Quantidade de dados nulos', anello.isna().sum().sum())

Então, será devolvido: “Quantidade de dados nulos: 0. Serão somados os 0 tanto dos dados nulos dos meses quanto das vendas.

Outra questão importante para nossos estudos será saber quais são os tipos de dados que teremos. Para descobri-los, vamos colocar:

anello.dtypes
Será informado que o mês é do tipo object, e as vendas, do tipo int64.

Como trabalharemos com Time Series, é importante que a coluna meses seja do tipo datetime, faremos a conversão do mês de um Pandas para time.

Para essa modificação, chamamos o mês e aplicamos o método to_datetime:

anello['mes'] = pd.to_datetime(anello['mes'])
anello.dtypes
O mês que era tipo object agora estará como datetime64. Com essa prática, nossos estudos serão facilitados.

Plotagem com Seaborn

Nesse momento, instalaremos o seabornpara poder criar nosso primeiro gráfico e visualizar o comportamento das nossas vendas.

Chamaremos o !pip install, e diremos que essa importação será na versão 0.9.0.

!pip install seaborn==0.9.0
import seaborn as sns
%matplotlib inline
from matplotlib import pyplot as plt

Faremos nosso primeiro plot a fim de compreender a performance das vendas da Anello & CIA. Para escrevermos o plot, precisamos de dois parâmetros.

sns.lineplot(x='mes', y='vendas', data = anello)
lineplot de vendas

À medida que o tempo passa, as vendas aumentam. Esse resultado satifaz qualquer empresário quanto aos resultados.

Entretanto, esse gráfico parecerá pobre por não ter um título, labels dos eixos x e y estarem muito pequenas. Poderemos melhorar a aparência dele para apresentá-lo num futuro relatório.

Aperfeiçoamento de Gráficos

Porém, nosso gráfico tem alguns aspectos a melhorar, ou seja, precisamos de várias modificações nesse gráfico para que ele transmita informações como queremos, logo, a visualização desse gráfico ainda poderá ser incrementada.

Urban Insitute Data Visualization

Existem alguns style guides que nos auxiliam na visualização dos gráficos.

Um deles é o Urban Institute , um data visualization style guide: https://github.com/UrbanInstitute/graphics-styleguide.

Esse guia nos auxilia dizendo quais os ajustes ideias para o tamanho do título, das labels e fornece um set de combinação de paleta de cores, dentre outras boas práticas com relação a essa criação.

Ajustando parâmetros de acordo com Urban institute:

Seguiremos as orientações principais desse padrão de ajustes.

sns.set_palette('Accent')
sns.set_style('darkgrid')
ax = sns.lineplot(x='mes', y='vendas', data = anello)ax.figure.set_size_inches(12,6)ax.set_title('Vendas Anello de 2017 e 2018', loc='left', fontsize=18)
ax.set_xlabel('Tempo', fontsize=14)
ax.set_ylabel('Vendas (R$)', fontsize=14)
ax = ax

Até agora, fizemos uma simples análise de dados. Criamos um gráfico mostrando as vendas com relação ao tempo. As séries temporais são uma coleção de observações feitas num espaço de tempo, que representará cada ponto. Conforme o tempo passa, teremos dados das vendas de cada mês.

Time Series do nosso dia a dia

Aprendemos que time series é uma coleção de observações ou dados, geralmente feita através de um tempo sequencial, que pode ser segundos, minutos, dias, meses, anos, entre outros.

Tipicamente, esse tempo é espaçado entre cada ponto de dados, que podemos medir o crescimento das vendas, como visto nesta primeira aula.

Decompondo as Vendas

Uma forma de extrair mais informações de nosso gráfico é decompor nossas vendas.

Existe uma função do Pandas para fazer isso. Criaremos uma variável para descobrir, de fato, de quanto foi o aumento de um mês para o outro.

Queremos a diferença de um mês para o anterior, usaremos a função diff:

anello['aumento'] = anello[['vendas']].diff()

Agora plotaremos um gráfico, da mesma forma que fizemos com as vendas, porém referente ao aumento dessa vez. Copiaremos todos os códigos usados para o gráfico anterior, fazendo as devidas alterações:

sns.set_palette('Accent')
sns.set_style('darkgrid')
ax: ax = sns.lineplot(x='mes', y='aumento', data = anello)ax.figure.set_size_inches(12,6)ax.set_title('Aumento das vendas da Anello de 2017 e 2018', loc='left', fontsize=18)
ax.set_xlabel('Tempo', fontsize=14)
ax.set_ylabel('Aumento', fontsize=14)
Plotagem com ajustes do Urban Institute Data Visualization

Criando função de plotagem

Em vez de ter que inserir todos esses códigos a cada vez que formos gerar um gráfico, tendo em vista que fizemos pequenas alterações do gráfico de vendas para o de aumento, criaremos uma função para ser chamada sempre que quisermos fazer um novo plot, alterando apenas alguns campos. o0Assim, nosso notepad ficará mais organizado.

Chamaremos nossa função de plotar_1. Ela terá algumas propriedades. Incluiremos os parâmetros passíveis de alteração, como: título, label x, label y, valor de x, valor de y e dataset:

def plotar_1(titulo, labelx, labely, x, y, dataset):
sns.set_palette('Accent')
sns.set_style('darkgrid')
ax = sns.lineplot(x=x, y=y, data=dataset)
ax.figure.set_size_inches(12,6)
ax.set_title(titulo, loc='left', fontsize=18)
ax.set_xlabel(labelx, fontsize=14)
ax.set_ylabel(labely, fontsize=14)
ax = ax

Então, passaremos apenas os argumentos dentro dos parâmetros já definidos na função:

plotar ('Aumento das vendas da Anello de 2017 e 2018', 
'Tempo',
'Aumento',
'mes',
'aumento',
anello)

Agora teremos uma função chamada plotar_1 que nos retornará um novo gráfico.

Haverá dois plots:

  • aumento das vendas da empresa ao longo dos meses do tempo
  • acréscimo mensal nas vendas

Também saberemos qual será a aceleração do crescimento. Criaremos uma coluna chamada aceleração, decompondo mais uma vez o dataset:

anello['aceleracao'] = anello['aumento'].diff()
Decomposição de Aceleração das vendas com .diff()
plotar_1(
'Aceleração das vendas da Anello de 2017 e 2018',
'Tempo',
'Aceleração',
'mes'
'aceleracao',
'anello')
Gráfico de Acelereção das vendas

Nesta escala de aceleração, vamos de 1 a 3, diferentemente das escalas dos outros gráficos. No caso das vendas, a escala parte de 0 a 700 e a decomposição de aumento, de 10 a 50.

Observação e Tendência

Criaremos um espaço para incluir todas essas decomposições.

Chamaremos o pyplotcomo plt, e passaremos um tamanho maior para que essa visualização fique adequada.

Como funcionam os subplots

subplot(3, 1, 2) — Aumento das Vendas

A divisão será de 3 partes e queremos preencher tudo, mas esse plot deverá estar embaixo, na segunda parte, ou seja, no meio da divisão. Então, passaremos (3, 1, 2) para o subplot.

Esse será nosso gráfico de aumento das vendas, então, copiaremos a linha do sns, trocando o y de vendas pelo aumento.

subplot(3, 1, 3) — Aceleração das Vendas

Por fim, queremos o mesmo para o terceiro gráfico. Pressionaremos “Ctrl C + Ctrl V” para copiar o colar o plt, substituindo a divisão (3, 1, 3), e da mesma forma, "Ctrl C + Ctrl V" para o sns, substituindo o y de aumento pela aceleração das vendas.

plt.figure(figsize = (16,12))
ax = plt.subplot(3,1,1)
ax.set_title('Análise das vendas da Anello 017 e 2018', fontsize=18, loc='left')
sns.lineplot(x='mes', y='vendas', data=alucar)
plt.subplot(3,1,2)
sns.lineplot(x='mes', y='aumento', data=alucar)
plt.subplot(3,1,3)
sns.lineplot(x='mes', y='aceleracao', data=alucar)
ax=ax
Subplots de Vendas

Usar ax para fazer ajustes

Se quisermos incluir as outras variações, como aumentar o tamanho das labels, basta usarmos o axe atribuir esses títulos para cada plot.

Então, copiaremos todo esse trecho de código e criaremos uma função chamada plot_comparaçao para utilizá-la nos próximos momentos em que precisarmos comparar três gráficos ao mesmo tempo.

Definindo agora função de padronização de plots de comparação

def plot_comparacao(x, y1, y2, y3, dataset, titulo):
plt.figure(figsize = (16,12))

ax = plt.subplot(3,1,1)
ax.set_title(titulo, fontsize=18, loc='left')
sns.lineplot(x=x, y=y1, data=dataset)

plt.subplot(3,1,2)
sns.lineplot(x=x, y=y2, data=dataset)

plt.subplot(3,1,3)
sns.lineplot(x=x, y=y3, data=dataset)
ax=ax

Executando plot de comparação:

plot_comparacao('mes', 'vendas', 'aumento', 'aceleracao', anello, 
'Análise das vendas da Anello de 2017 e 2018')

Ter este tipo de plotagem, esclarece como os gráficos juntos mostram que há aumento das vendas conforme o passar dos meses, o crescimento mês a mês e a aceleração desse movimento. Em resumo, com uma melhor visualização dos gráficos, nossas análises ficam mais assertivas.

Autocorrelação

A autocorrelação é uma medida de correlação entre as observações de uma série temporal. Com a autocorrelação descobriremos se os valores obtidos pela empresa nessa semana estão relacionados aos da semana passada.

Para entender melhor o funcionamento dela, comparamos os valores com suas próprias correlações, ou seja, consigo mesmas.

Cada passo dado pelo gráfico de correlação será chamado de Lag. Então, a cada passo que damos, verificaremos a correlação entre os valores da observação com eles mesmos.

No lag 1, faremos o que foi citado: compararemos os valores com eles mesmos, movimentando-os. Então, conforme passamos os Lags, executamos as comparações para encontrar o nível de correlação.Os valores serão sempre baseados nessa distribuição. O nível de correlação máxima será 1 e o nível de correlação mínima será -1.

Vamos criar esse gráfico de correlação para descobrir os valores das nossas vendas comparando com as vendas de tempos anteriores. Em primeiro lugar, importaremos a biblioteca capaz de gerar esse gráfico:

from pandas.plotting import autocorrelation_plot

Vamos executar e já poderemos utilizar essa biblioteca. Portanto, como quero descobrir o nível de correlação das vendas, pegaremos o DataFrame anello e a Series vendas:

autocorrelation_plot(alucar['vendas'])

Nesse gráfico, haverá uma correlação significativa no Lag1 que descrescerá com o passar do tempo, até se tornar nula.

Poderemos reparar nesse gráfico, então, que os 7 primeiros dias parecerão ter uma forte ligação com a semana passada, porque a correlação estará alta nesse período. Com o passar do tempo ela será menor até a nulidade.

Nosso código ficará assim, em ordem:

ax = plt.figure(figsize = (12,6))
ax.suptitle('Correlação das Vendas')
autocorrelation_plot(anello['vendas'])
ax=ax
Correlação das vendas de uma semana para a outra

Já temos nosso gráfico e entendemos a finaalidade da autocorrelação. Agora, podemos calcular a correlação não só das vendas, como também da decomposição do aumento e da aceleração.

Autocorrelação para a decomposição de Aumento

Copiaremos o código e faremos as devidas alterações para a correlação do aumento:

ax = plt.figure(figsize = (12,6))
ax.suptitle('Correlação do Aumento')
autocorrelation_plot(anello['aumento'])
ax=ax
Erro na execução por falta de ajuste do pindice

A execução gera um gráfico sem nada. Isso acontece porque os nossos valores do aumento começam a partir do índice 1, pois ele é calculado a partir da diferença das vendas entre o índice 1 e o índice 0.

Passaremos o índice 1 para nossa função autocorrelation_plot:

autocorrelation_plot(alucar['aumento'][1:])
Correlação do aumento das vendas

Executando, teremos a correlação do aumento, bastante semelhante ao gráfico de correlação das vendas.

Autocorrelação para a decomposição de Aceleração

Relembrando que precisaremos atribuir o valor a partir do índice 2 da aceleração e teremos o índice de correlação.

ax = plt.figure(figsize = (12,6))
ax.suptitle('Correlação da aceleração', fontsize=18, x=0.26, y=0.95)
autocorrelation_plot(alucar['aceleracao'][2:])
ax = ax
Correlação da aceleração das vendas

A partir desses gráficos, podemos concluir que os 7 primeiros dias parecem ter uma ligação muito forte com o da semana passada.

Com o passar dos Lags essa correlação tende a decrescer...

Até aqui vimos:

  • Aplicação da técnica de Decomposição de uma Time Series, para mensurar o crescimento mês a mês
  • A função diff() para decomposição das vendas para criar o aumento, e a partir aumento para descobrir a aceleração
  • A função de autocorrelation_plot()para descobrir o nível de correlação das vendas, do aumento e da aceleração
  • Criação de uma função chamada plotar_1() e plot_comparacao() para geração de gráficos padronizados, evitando código duplicado e redundante.

Continua…

Composing a repository of books (i bought), authors (i follow) & blogs (direct ones) for my own understanding.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store