Pandas Time Series (Pt. II/II)

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

Na parte I do nosso Pandas Time Series abordamos a plicação das técnicas de:

  • decomposição de uma Time Series, para mensurar o crescimento no período,
  • diff() para decomposição das vendas no tempo,
  • autocorrelation_plot()para descobrir o nível de correlação das vendas e,
  • criação de funções para geração de gráficos padronizados, evitando código duplicado e redundante.

Nesta parte II, 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.

Analisando Assinantes da Anello & Cia

A partir de agora vamos analisar o crescimento de assinantes da Newsletter da Anello e verificar as vendas no período a fim de estudar um componente geralmente presente nas time series e nas nossas vidas: a Sazonalidade.

A Anello possui uma Newsletter mensal sobre descontos e promoções. Depois de dois anos da criação dessa Newsletter, foi solicitada uma análise para descobrir o impacto dessa Newsletter e o efeito sobre seus assinantes.

Podemos ler o arquivo “newsletter.csv”, vamos primeiro armazená-lo em uma variável. Chamaremos essa variável de “assinantes”. Também escreveremos o cabeçalho para visualizar os 5 primeiros itens desse arquivo.

assinantes = pd.read_csv('newsletter_anello.csv') 
assinantes.head()
df assinantes

Teremos lido, armazenado na variável e pedido para ler os primeiros registros. Existirá uma coluna para o mês. Já sabemos que há 2 anos de Newsletter, desde que a empresa foi aberta. Outra coluna será para a quantidade de assinantes que tivemos a cada mês.

Agora, descobriremos se os assinantes têm crescido ou diminuído. Como estamos trabalhando com Time Series, nosso mês deve ser tipado como datetime:

assinantes.dtypes

Veremos que nosso mês será do tipo object, então faremos a devida alteração. Antes disso, veremos primeiro qual é a quantidade de linhas e colunas e a de dados nulos, gerando prints.

print('Quantidade de linhas e colunas', assinantes.shape)
print('Quantidade de dados nulos', assinantes.isna().sum().sum())

Nos será devolvido que em 2 anos de registros haverá 24 linhas (referentes aos meses) e 2 colunas, e 0 dados nulos. Portanto, foram realmente colhidas informações para todos os meses.

Converteremos o tipo do mês para datetime:

assinantes['mes'] = pd.to_datetime(assinantes['mes'])

Com o conhecimento que já adquirimos no DataFrame da Anello, aplicaremos diff para descobrir o aumento e a aceleração do número de assinantes.

Então, com o diff dos assinantes, descobrimos o aumento e aceleração:

assinantes['aumento'] = assinantes ['assinantes'].diff()
assinantes['aceleracao'] = assinantes ['aumento'].diff()
assinantes.head()

Para conferir, escrevemos assinantes.head e teremos o resultado de que no mês 1 ainda não tínhamos nenhum assinante.

Teremos um plot de comparação para exibir os 3 itens. Se escrevermos “plot_" e pressionarmos o "Tab" o programa já fornecerá a função de comparação plot_comparacao (x, y1, y2, y3, dataset, titulo). Completaremos:

plot_comparacao('mes', 
'assinantes',
'aumento',
'aceleracao',
assinantes,
'Análise de assinantes Newsletter da Anello & Cia')
subplots Newsletter

A aceleração começa positiva, porém, se torna negativa significantemente.

No mês 10 de 2018, em acelereção, podemos notar uma retomada após chegar a -5 antes de sua retomada.

Com esses gráficos, veremos que decompondo as vendas poderemos encontrar casos muito interessantes. Se tivéssemos só o gráfico da análise de assinantes, acharíamos que a tendência seria ao crescimento expressivo, ainda que regredindo.

Fazendo a decomposição, vemos que de fato houve um crescimento, mas depois o aumento do número de assinantes cai de forma notória. Também ocorre desaceleração dos assinantes da Newsletter num determinado momento, havendo aceleração negativa, mas no acumulado cada vem mais assinantes.

Sazonalidade dos Chocolates Anello

Existe uma empresa grande no ramo alimentício que nos solicitou uma análise a respeito das vendas de água, a Chocolates Anello.

O problema em questão

O problema é que em determinado período do ano, a empresa não dá conta da demanda. Por mais que produza, não tem sido o suficiente. Tentaremos descobrir o que se passa com as vendas de chocolates da Anello em certos período.

chocolates = pd.read_csv('chocolates_anello.csv')
chocolates.head()

Teremos uma tabela com uma coluna para os meses e outra para a quantidade de vendas referentes a cada mês

Visualizaremos os tipos com:

chocolates.dtypes

O mês será do tipo object, então, vamos transformá-lo em datetime:

chocolates['mes'] = pd.to_datetime(chocolates['mes'])
chocolates.dtypes

Conferiremos se há algum dado nulo e a quantidade, bem como o número de linhas com prints:

print ('Quantidade de linhas:', chocolates.shape)
print ('Quantidade de dados nulos:', chocolates.isna.sum().sum())

Agora, vamos fazer o diff do aumento e aceleração das vendas:

chocolates['aumento'] = chocolates['vendas'].diff()
chocolates['aceleracao'] = chocolates['aumento'].diff()
chocolates.head()

Plot de Comparação

Agora, faremos o plot de comparação. Escrevendo “plot_" o programa já completará com a comparação e os parâmetros. Nós os definiremos:

plot_comparacao(
'mes',
'vendas',
'aumento',
'aceleracao',
chocolate,
'Análise de vendas dos Chocolates Anello de 2017 a 2018')

Ao executarmos, teremos um plot diferente dos anteriores.

Começando com a análise de vendas, teremos logo de cara uma queda nas vendas no mês de 2017–01, um aumento no mês 4, seguido de uma queda abrupta novamente.

De 2017–07 a 2018–01 têm-se uma estabilidade baixa nas vendas e ocorre novamente uma queda, se repetindo o “mesmo” crescimento em 2018–04 e decaindo próximo ao mês 5, retomando em 6 e decaindo em 7. Ou seja, o que acontece é que podemos encontrar algo interessante com relação a Time Series: a sazonalidade.

Padrão repetitivo dentro de um intervalo fixo

A sazonalidade é um padrão repetitivo dentro de um determinado período fixo. Ou seja, sempre no mês 4 e no 6 a empresa venderá mais chocolate. Durante os demais meses, tende a vender menos.

Esse comportamento é muito característico das séries temporais. Podemos vê-lo também no aumento. Há um aumento no mês 4 de acordo com o gráfico, e uma grande queda na sequência.

Até na aceleração do aumento das vendas é possível visualizar esse crescimento. isso significa que o padrão de sazonalidade é muito marcante, pois se mantém em ambos os gráficos de aumento e aceleração.

Agora que já sabemos o que é sazonalidade, pensemos por que esse fenômeno ocorre nesses meses. No mês 4 de todos os anos costuma haver a data da Páscoa e em Junho, o Dia dos Namorados. As vendas de chocolates, pelo gráfico de vendas, são até maiores em Junho do que em Abril.

Portanto, nessas datas, temos essa sazonalidade bem delineada

Investigando a Sazonalidade na loja de São Caetano do Sul

A Chocolates Anello possui diversas franquias espalhadas pelo país, cada uma com seus gerentes, suas regras de negócios e seus vendedores.

Uma loja em especial chamou muito a atenção dos diretores da empresa pelas vendas diárias nos meses de Outubro e Novembro de 2018. Utilizaremos o arquivo “vendas_por_dia.csv”:

vendas_por_dia = pd. read_csv('vendas_por_dia.csv')
vendas_por_dia.head()

Teremos uma coluna para o dia e outra para a quantidade de vendas referente a esta loja.

Vamos conferir com prints se há algum dado nulo e quantos são, além do número de linhas.

print ('Quantidade de linhas:', vendas_por_dia.shape)
print ('Quantidade de dados nulos:', vendas_por_dia.isna.sum().sum())

São 61 linhas (61 dias) e 2 colunas, ou seja, os meses inteiros de Out e Nov. Não temos dados nulos e podemos prosseguir na análise.

Conferindo os tipos de dados:

vendas_por_dia.dtypes

O dia estará tipado como object do Pandas, então, vamos transformá-lo em datetime64:

vendas_por_dia['dia'] = pd.to_datetime(vendas_por_dia['dia'])
vendas_por_dia.dtypes()

Faremos, então, um diff do aumento e das vendas para descobrir a aceleração das vendas:

vendas_por_dia['aumento'] = vendas_por_dia['vendas'].diff()
vendas_por_dia['aceleracao'] = vendas_por_dia ['aumento'].diff()

Plot de Comparação

Agora, faremos o plot de comparação dos três gráficos. Escrevendo “plot_" e dando um "Tab" o programa já completará com a comparação e os parâmetros "plot_comparacao (x, y1, y2, y3, dataset, titulo)". Nós os definiremos como:

plot_comparacao(
'dia',
'vendas',
'aumento',
'aceleracao',
vendas_por_dia,
'Análise de vendas de Out e Nov - Loja São Caetano do Sul).

Executaremos o código e os gráficos serão plotados. Vamos analisá-los e serão bem diferentes do que vimos até então. As vendas terão um padrão sazonal mais uma vez, pois estão repetidamente aumentando e diminuindo na sequência, mas diferentemente do gráfico da aula anterior, isso não ocorrerá especificamente em duas datas do comemorativas. Teremos que explorar a razão disso.

Para escrever o código que gera a coluna nova, pegaremos nosso DataFrame e a coluna do dia, e precisaremos saber qual será o dia da semana relacionado a esse dia do Data. Existe uma função para isso:

vendas_por_dia['dia_da_semana'] = vendas_por_dia ['dia'].dt.day_name()
vendas_por_dia.head()

Porém, os dados estarão todos em inglês (Monday, Tuesday, Wednesday, etc.). Vamos simplificar deixando-os em Português.

Pegaremos todos os dados de dias da semana e usaremos o unique, que nos retornará todos os valores únicos quanto aos dias da semana.

vendas_por_dia['dia_da_semana'].unique()

Então, criaremos um dicionário próprio com esses valores. Geraremos uma variável chamada dias_traduzidos:

dias_traduzidos = {
'Monday': 'Segunda',
'Tuesday': 'Terça',
'Wednesday':'Quarta',
'Thursday':'Quinta',
'Friday':'Sexta',
'Saturday':'Sábado',
'Sunday':'Domingo'}

Agora, precisaremos mapear esses dias da semana pelos dias da semana traduzidos. Na sequência já visualizaremos por 2 semanas se a alteração foi efetuada corretamente, passando 14 dias para head.

vendas_por_dia['dia_da_semana'] = vendas_por_dia['dia da semana'].map(dias_traduzidos)
vendas_por_dia.head (14)

Podemos observar que nos sábados e domingos e no feriado do dia 12 de Out. as vendas foram bem menores do que em comparação com os dias da semana. Isso pode significar que a empresa durante esses dias não abra durante todo o horário comercial, ou não disponibilize todos os seus vendedores, porque há vendas, mas elas são diminutas.

Para conseguir afirmar categoricamente se as vendas sempre são menores aos finais-de-semana, vamos agrupar e obter médias dos valores de cada dia da semana. Faremos isso não só para as médias das vendas, como também para o aumento e a aceleração.

Agrupando dias da semana

Agruparemos os dias da semana e calcularemos as médias. Antes, criaremos uma variável, vendas_agrupadas:

vendas_agrupadas = vendas_por_dia.groupby('dia_da_semana)[
'vendas',
'aumento',
'aceleracao'].mean().round()`
  • No Domingo, a média das vendas será 19.0 e do aumento, 3.0.
  • No Sábado, a média das vendas será 16 e a do aumento -28.0.

Então sábado de fato será o dia mais fraco para as vendas. Nos demais dias, exceto por Sexta (45.0), Sábado e Domingo, a média das vendas será sempre maior do que 50.

ax = plt.figure(figsize = (12,6))
ax.suptitle('Correlação vendas diárias', fontsize=18, x=0.3, y=0.95)
autocorrelation_plot(vendas_por_dia['vendas'])
ax = ax
ax = plt.figure(figsize = (12,6))ax.suptitle('Correlação aumento vendas diárias', fontsize=18, x=0.35, y=0.95)autocorrelation_plot(vendas_por_dia['aumento'][1:])ax = ax
ax = plt.figure(figsize = (12,6))ax.suptitle('Correlação da aceleração das vendas diárias', fontsize=18, x=0.35, y=0.95)autocorrelation_plot(vendas_por_dia['aceleracao'][2:])ax = ax

Podemos concluir analisando a sazonalidade que as quedas representadas no gráfico serão referentes aos finais-de-semana. Por alguma regra dos negócios da empresa, esses dias, contando com feriados, contaram bastante para a tendência que nosso gráfico apresentará.

Conteúdo abordado até aqui:

  • Vimos a importância da técnica de decomposição na análise dos assinantes da Newsletter da Anello,
  • Analisamos as vendas da Show Cacacau e descobrimos um padrão repetitivo no movimento das vendas dentro de um período fixo, na qual é chamado de Sazonalidade,
  • Examinamos as vendas de uma determinada loja da Show Cacau nos meses de Out e Nov de 2018, e descobrimos que também havia uma sazonalidade,
  • Investigamos o que causava a sazonalidade da loja.

Normalização

Continuando nossos estudos, agora analisaremos as vendas de nossa cafeteria, a Cafeteri Bialetti.

Criaremos uma variável chamada cafeteria para a leitura do arquivo csv. Depois, visualizaremos os primeiros registros com o head.

cafeteria = pd.read.csv('cafeteria_bialetti.csv')
cafeteria.head

O documento terá as colunas mês e vendas. Conferiremos como o mês estará tipado.

cafeteria.dtypes

O mês estará do tipo object, e alteraremos isso para datetime64.Depois de executar, faremos a prova real com outro cafeteria.dtypes.

cafeteria['mes'] = pd.to_datetime(cafeteria['mes'])
cafeteria.dtypes

Vamos conferir se temos dados nulos e quantos serão os dados nesse arquivo.

print('Quantidade de linhas e colunas:', cafeteria.shape)
print('Quantidade de dados nulos:', cafeteria.isna().sum.sum()

Agora faremos um primeiro plot. Mas, em vez de fazer o diff, nesse caso faremos o plot apenas de um gráfico. Usaremos a função plotar_1 e preencheremos de acordo com a sugestão do próprio programa plotar_1(titulo, labelx, labely, x, y, dataset). É importante lembrar que o DataSet não será uma string.

Queremos plotar as vendas da Cafelura de 2017 e 2018.

plotar('Vendas da Cafelura de 2017 e 2018, 'Tempo', 'Vendas', 'mes', 'vendas', cafelura)

Vamos rodar esse código, e teremos criado um gráfico interessante que mostrará que a empresa está crescendo. Porém, há alguns pontos diferentes, por exemplo, alguns em que parece ter ocorrido mais vendas. Teremos que conferir se poderemos normalizar esse gráfico.

A normalização é uma prática comum do trabalho com Time Series. Geralmente, a quantidade de dias úteis do mês, de dias da semana ou até dias úteis são técnicas utilizadas para normalizar séries temporais.

Já teremos disponibilizado no material do nosso curso um arquivo chamado “dias_final_de_semana.csv”, que reúne os dias de finais de semana que tivemos a cada mês dos anos de 2017 e 2018. Normalizaremos cada mês nos baseando nos dias de finais de semana e veremos como será gerado outro gráfico diferente.

Para começar, carregaremos nosso novo DataFrame.

quantidade_de_dias_de_fds = pd.read_csv('dias_final_de_semana')

Teremos a coluna quantidade_de_dias. Então, pegaremos a quantidade_de_dias_de_fds e dentro dessa coluna, estabeleceremos que sejam trazidos apenas os valores dentro de uma array.

quantidade_de_dias_de_fds['quantidade_de_dias'].values

Nos será devolvido a quantidade de dias de finais de semana que tivemos no mês 1, no 2 e assim respectivamente. Agora que teremos esses valores, dividiremos o número das vendas pela quantidade de finais de semana que tivemos. Em seguida, já visualizaremos os primeiros registros.

cafeteria['vendas_normalizadas']= cafeteria['vendas']/quantidade_de_dias_de_fds['quantidade_de_dias'].valuescafeteria.head

Executaremos e teremos, então, o mês, o valor das vendas e o valor das vendas normalizadas.

Faremos um plot das vendas normalizadas, portanto. Chamaremos a função plotar e completaremos os campos. plotar(titulo, labelx, labely, x, y, dataset)

plotar('Vendas normalizadas da Cafeteria Bialetti de 2017 a 2018',
'Tempo', 'Vendas normalizadas', 'mes', 'vendas_normalizadas',
cafeteria)

Ao normalizar as vendas dividindo pela quantidade de finais de semana que temos, nosso gráfico será totalmente diferente do anterior, mostrando apenas uma curva de crescimento. Vamos criar um plot para comparar ambos os gráficos.

Nesse caso não teremos 3, apenas 2 no subplot. Queremos que todo o espaço seja ocupado e que o primeiro plot seja o primeiro gráfico.

plt.figure(figsize=(12,8))
ax=plt.subplot(2,1,1)
ax.set_title('Vendas Cafelura 2017 e 2018', fontsize=18)
sns.lineplot(x='mes', y='vendas', data=cafelura)
ax=plt.subplot(2,1,2)
ax.set_title('Vendas normalizadas Cafelura 2017 e 2018', fontsize=18)
sns.lineplot(x='mes', y='vendas_normalizadas', data=cafelura)
ax=ax

Então teremos as duas formas das vendas apresentadas nos gráficos, tanto as vendas quanto as vendas normalizadas de acordo com a quantidade de dias de finais de semana.

Statsmodel

Sempre que vamos estudar uma série temporal temos que ter em mente componentes como a tendência.

Por exemplo, na análise que fizemos das vendas da Anello & Cia, a tendência é o crescimento, ou seja, esse movimento da série de valores se torna mais alto. Ela se difere da análise que fizemos do aumento de assinantes da newsletter, que começou com uma tendência de crescimento, mas depois houve uma queda muito significativa.

Outro ponto muito importante e presente nas Time Series, além da tendência, é a sazonalidade. Nos casos que analisamos em aulas anteriores tivemos sempre dois pontos (ou meses) em que as vendas estouraram, ou vimos vendas maiores durante a semana do que aos finais-de-semana.

Isso significa que a sazonalidade se refere a um padrão repetitivo dentro de um período fixo de tempo.

Também teremos que ter claro que os ruídos serão comuns nas séries temporais, e pensaremos em formas de normalizar esses ruídos, assim como normalizamos os picos de vendas por quantidade de dias de finais de semana se tratando das vendas da Cholates Anello, e tivemos um gráfico com uma linha mais homogênea.

Sempre que analisarmos Time Series será necessário identificar componentes como a tendência, a sazonalidade e essas variações aleatórias, os ruídos. Esses elementos sempre serão presentes nas séries temporais.

Tudo de uma vez só…

Será que existe alguma forma de passar os dados e eles nos mostrarem o que será a tendência, a sazonalidade e o ruído de uma só vez?

Faremos a importação dessa biblioteca.

from statsmodels.tsa.seasonal import seasonal_decompose

Para esse exemplo, a lista que passaremos será a de vendas da Chocolates Anello . Nesse código teremos que passar o parâmetro da frequência, que deverá ser um número inteiro a ser exibido. Atribuiremos esse resultado a ax e faremos um plot dele.

resultado = seasonal_decompose(chocolura['vendas'], period=1)
ax = resultado.plot()

Receberemos os nossos próprios dados das vendas, assim como gráficos de tendência, sazonalidade e ruído. Vamos mudar a frequência para 2.

Quando executarmos, a observação continuará a mesma, mas nossa tendência será alterada. A sazonalidade seguirá um padrão de ascender e cair. E teremos bastante ruído.

Com a frequência 3,teremos o crescimento no ponto da observação. Na tendência, o valor aumentará, cairá, depois aumentará e cairá de novo. A sazonalidade segue o padrão e o ruído não traz o início. Isso indica que começamos a perder referência conforme o nível de frequência que colocamos.

Por exemplo, se colocarmos 10, não conseguiremos ver mais alguns dados na tendência nem no ruído. A sazonalidade ficará semelhante à própria observação apesar de distorções do gráfico.

Usaremos a frequência 3. Vamos exibir esses gráficos em tamanho maior utilizando nossa função plot_comparacao. Para isso, chamaremos as respectivas variáveis.

observacao = resultado.observed
tendencia = resultado.trend
sazonalidade = resultado.seasonal
ruido = resultado.resid

Armazenamos a lista em todas as variáveis. Agora, criaremos um DataFrame com todos esses valores. Visualizaremos ele logo depois.

data = ({
'observacao':observacao,
'tendencia':tendencia,
'sazonalidade':sazonalidade,
'ruido':ruido
})
resultado = pd.DataFrame(data)
resultado.head()

Serão mostradas as colunas e os valores. Agora faremos o plot de comparação, passando os parâmetros.

Visualizando Tendência

plot_comparacao(resultado.index, 'observacao', 'tendencia', 'sazonalidade', resultado,'Exemplo com Statsmodels')

Teremos a observação; a tendência, em que o gráfico sobe e depois sofre uma queda; e a sazonalidade, em que há aumento e queda repetidas vezes.

Em vez de sazonalidade, podemos chamar esse parâmetro de ruído no código para visualizá-lo.

Visualizando Ruído

plot_comparacao(resultado.index, 'observacao', 'tendencia', 'ruido', resultado, 'Exemplo de Statsmodels')

Então, teremos o valor do ruído dessa nossa observação. Mas deixaremos mesmo como a sazonalidade, pois criamos uma função para plotar apenas 3 gráficos.

O Statsmodels é um exemplo de como podemos utilizar uma função para visualizar todas as informações que desejamos. Vimos também que a frequência é muito importante para que os resultados sejam visualizados corretamente.

Até aqui abordamos:

  • Aplicamos a função de autocorrelação nas vendas, no aumento e na aceleração das vendas diárias e vimos que havia uma correlação entre elas
  • Executamos uma técnica de normalização de time series para minimizar as frequências pela quantidade de dias de finais de semana de cada mês
  • Analisamos uma Time Series importando da biblioteca statsmodels.tsa.seasonal a função seasonal_decompose, que nos mostra o que é a nossa observação, tendência, sazonalidade e ruído de uma só vez.

Ruído de uma Série Temporal

Nos foram passados os dados de uma determinada empresa do ramo de telefonia e celulares. Foi pedido que avaliássemos o rendimento da empresa:

celular = pd.read_csv('celulares.csv')
celulares.head()

Uma coluna de dias do mês de Out de 2018 e uma para as vendas respectivas dos dias.

Vamos conferir como o dia estará tipado com um celular.dtypes. Ele será um object, e temos que alterá-lo para datetime64.

celular['dia'] = pd.to_datetime(celular['dia'])
celular.dtypes

Agora temos que nos certificar de que não há dados nulos. Esse é um passo importante e que temos visto em diversas aulas, porque se por acaso existir um dado nulo de vendas em um dia e isso representar uma queda drástica no gráfico, nossa análise se modificará drasticamente. Então, vamos criar os prints.

print('Quantidade de linhas e colunas:', celular.shape)
print('Quantidade de dados nulos:', celular.isna().sum().sum())

Teremos 61 linhas e 2 colunas e nenhum dado nulo, ou seja, dados para todos os dias de 2 meses.

Faremos o diff para comparar o aumento e a aceleração, e visualizaremos os primeiros registros em seguida.

celular['aumento'] = celular['vendas'].diff()
celular['aceleracao'] = celular['aumento'].diff()

Teremos as colunas para o aumento e a aceleração. Plotaremos o gráfico para entender o comportamento das vendas da empresa.

plot_comparacao('dia', 'vendas', 'aumento', 'aceleracao', celular, 'Análise de vendas de Celular de Outubro e Novembro de 2018')

Terá sido plotado um gráfico com muito ruído. A pergunta que nos foi feita quando recebemos esses dados foi se a empresa continuará crescendo e tendo boas vendas ou não.

Nosso gráfico de vendas, como vimos, tem bastante ruído. O de aumento se manteve linear no início, mas teve uma queda importante um pouco antes do dia 15.

Analisando a aceleração, também tivemos valores positivos a princípio, e depois uma queda bastante drástica. Mas no geral, há ruído em grande parte pontos.

Aprenderemos uma técnica para normalizar essas linhas com as médias móveis, sabendo os benefícios e cuidados que precisaremos tomar ao aplicar a normalização.

Médias Móveis para redução de ruídos

Existe uma técnica muito conhecida e utilizada para a redução desses ruídos, a Média Móvel. A ideia é tentar minimizar os ruídos de uma série temporal através de médias móveis, pegando dois ou mais pontos e calculando uma média de 7 dias entre eles. Depois, é calculada a média de mais 7 dias, e os pontos serão marcados para minizar a dispersão da frequência.

Já há uma função no Pandas para o cálculo, a rolling. Especificaremos no nosso código que queremos a média para 7 dias, e na sequência, também colocaremos mean (média):

celular['media_movel'] = celular['vendas'].rolling(7).mean()

Vamos rodar esse código e visualizaremos uma coluna com valores vazios para os primeiros 6 dias e a média calculada para o 7° dia. Agora plotaremos o gráfico para poder visualizar e comparar com o gráfico das vendas sem a média móvel.

Usaremos a função plotar que criamos:

plotar('Análise de vendas com média móvel de 7 dias', 'Tempo', 'Média Móvel', 'dia', 'media_movel', celular)

Executaremos, e teremos um gráfico bem diferente do primeiro. Já não teremos tantos ruídos na nossa série.

Mas a Média Móvel não precisa ser sempre de 7 dias. Dependendo do caso que estaremos estudando, isso pode ser alterado. Criaremos uma nova média para 21 dias:

celular['media_movel_21'] = celular['vendas'].rolling(21).mean()plotar('Análise de vendas com média móvel de 21 dias', 'Tempo', 'Média Móvel', 'dia', 'media_movel_21', celular)

Agora que aplicamos a técnica pegando 21 pontos, tirando a média e criando um ponto a partir dela, as frequências do gráfico foram normalizadas. No entanto, se fizermos um rolling muito grande, começamos a perder informações.

O gráfico faz parecer que a empresa estará vendendo bem e diferentemente da média de 7 dias, não exibe alterações mais significantes. Precisaremos saber até que ponto chegar com a aplicação da técnica de Média Móvel.

Para finalizar, vamos plotar os trẽs gráficos junto. o de vendas, o da Média Móvel de 7 dias e o da Média de 21 dias. Usaremos o plot_comparacao.

plot_comparacao('dia', 'vendas', 'media_movel', 'media_movel_21', celular, 'Comparando as médias móveis')

Os três escrevem as mesmas informações sobre as vendas da empresa, com a diferença da normalização que ocorre de forma mais suave na Média Móvel de 7 e mais intensificada na de 21. Mesmo na média de 21 dias vemos que houve uma queda acentuada.

É importante conhecermos essa técnica para poder enxergar melhor a linha no gráfico com os ruídos, porém, tomando sempre cuidado, para não exagerar e alterar demais o caráter das informações.

Obrigado…

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