Médias Móveis

Conceitos, cálculos e visualização.

Mario O. de Menezes https://momenezes.github.io/tutorials
09-25-2021

Médias Móveis

Média móvel é um recurso muito utilizado em dados do tipo séries temporais; sua aplicação é para suavizar uma série, permitindo que sejam mais facilmente observados comportamentos e tendências nesses dados.

A ideia é que cada ponto original será subsituído pela média dos pontos vizinhos, definidos através de uma janela de largura \(w\), que vai se movimentando pelos pontos.

Média Móvel

Uma das escolhas possíveis ao se calcular uma média móvel é quem será o elemento de referência (alinhamento) da média. Na figura mostrada acima, temos 3 possíveis escolhas, ou alinhamentos, indicados:

O impacto desta escolha será na localização dos elementos não presentes (\(w-1\)) no vetor resultante:

Na figura abaixo temos uma ilustração da média móvel com alinhamento à esquerda em uma janela de 5 elementos; note como os 4 últimos elementos finais estarão faltando (NA).

Média Móvel Alinhamento à Esquerda

Fazendo no R

Vetor mostrado na figura acima

vt <- c(5,7,6,4,7,9,12,8,14,17,23,31,27,29,35,45,32,29,55,49)

Para fazer a média móvel, vou usar a função frollmean do pacote data.table. A síntaxe (simplificada) desta função é:

Alinhamento à esquerda

frollmean(vt, n = 5, align = "left")
 [1]  5.8  6.6  7.6  8.0 10.0 12.0 14.8 18.6 22.4 25.4 29.0
[12] 33.4 33.6 34.0 39.2 42.0   NA   NA   NA   NA

Alinhamento central

frollmean(vt, n = 5, align = "center")
 [1]   NA   NA  5.8  6.6  7.6  8.0 10.0 12.0 14.8 18.6 22.4
[12] 25.4 29.0 33.4 33.6 34.0 39.2 42.0   NA   NA

Alinhamento à direita

frollmean(vt, n = 5, align = "right")
 [1]   NA   NA   NA   NA  5.8  6.6  7.6  8.0 10.0 12.0 14.8
[12] 18.6 22.4 25.4 29.0 33.4 33.6 34.0 39.2 42.0

Dados em um data.frame

Vamos agora calcular as médias móveis de uma variável em um data.frame; vou utilizar um dataset resultante dos casos de Covid-19 no Estado de São Paulo, de 25/Fevereiro/2020 a 09/Outubro/2020, ou seja, 228 dias. Estes dados foram originalmente baixados (em 04/Nov/2020) do projeto Brasil.io

Leitura dos dados

library(readr)
casos_SP <- read_csv("data/dataset.csv", 
    col_types = cols(date = col_date(format = "%Y-%m-%d"), 
        casos = col_integer()))

Pequena inspeção da estrutura do arquivo

str(casos_SP)
spec_tbl_df [228 × 2] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ date : Date[1:228], format: "2020-02-25" ...
 $ casos: int [1:228] 1 0 0 1 0 0 0 0 1 3 ...
 - attr(*, "spec")=
  .. cols(
  ..   date = col_date(format = "%Y-%m-%d"),
  ..   casos = col_integer()
  .. )
 - attr(*, "problems")=<externalptr> 

Início e Final

head(casos_SP)
# A tibble: 6 × 2
  date       casos
  <date>     <int>
1 2020-02-25     1
2 2020-02-26     0
3 2020-02-27     0
4 2020-02-28     1
5 2020-02-29     0
6 2020-03-01     0
tail(casos_SP)
# A tibble: 6 × 2
  date       casos
  <date>     <int>
1 2020-10-04   473
2 2020-10-05   677
3 2020-10-06  6260
4 2020-10-07  5916
5 2020-10-08  5649
6 2020-10-09  5786

Calculando Média Móvel

Para usar as funcionalidades do data.table precisamos transformar nosso data.frame em um tipo data.table.

setDT(casos_SP)
casos_SP[, ma5esq := frollmean(casos, n = 5, align = "left")] # alinhamento à esquerda
casos_SP[, ma5center := frollmean(casos, n = 5, align = "center")] # alinhamento central
casos_SP[, ma5dir := frollmean(casos, n = 5, align = "right")] # alinhamento à direita

Veja como os NAs aparecem no data.frame:

casos_SP
           date casos ma5esq ma5center ma5dir
  1: 2020-02-25     1    0.4        NA     NA
  2: 2020-02-26     0    0.2        NA     NA
  3: 2020-02-27     0    0.2       0.4     NA
  4: 2020-02-28     1    0.2       0.2     NA
  5: 2020-02-29     0    0.2       0.2    0.4
 ---                                         
224: 2020-10-05   677 4857.6    3884.4 3790.2
225: 2020-10-06  6260     NA    3795.0 3822.8
226: 2020-10-07  5916     NA    4857.6 3884.4
227: 2020-10-08  5649     NA        NA 3795.0
228: 2020-10-09  5786     NA        NA 4857.6

Visualizando os dados

Vamos usar duas bibliotecas para esta visualização; o gráfico final em ambas será um plot.ly, mas construído de formas diferentes. As bibliotecas são ggplot2 e plotly

# função auxiliar para formatar os números
numero_int <- scales::label_comma(accuracy = 1, big.mark = ".", decimal.mark = ",")

ggplotly

g <- ggplot(casos_SP) + geom_point(aes(x= date, y = casos), color = "gray") + 
  geom_line(aes(x = date, y = ma5center), color = "blue") +
  geom_line(aes(x = date, y = ma5esq), color = "green") +
  geom_line(aes(x = date, y = ma5dir), color = "red") +
  labs(x = "") +
  theme_light()
ggplotly(g)

Um zoom na parte final do gráfico mostrando as médias móveis.

Zoom no gráfico das Médias Móveis ggplotly

plot.ly

p <- plot_ly(casos_SP, hoverinfo = 'text', 
               text  = ~paste('<br>Data:', date,
                             '<br>Casos Dia:', numero_int(casos),
                             '<br>MA 5cent:', numero_int(ma5center),
                             '<br>MA 5esq:', numero_int(ma5esq),
                             '<br>MA 5dir:', numero_int(ma5dir)),  
               showlegend = FALSE, colorscale = "Jet")
p <- p %>% add_trace(x = casos_SP$date, y = casos_SP$casos, type = "scatter", 
              mode = "lines+markers", line = list(color = 'rgb(100, 100, 100)', 
              width = 1), marker = list(color = 'rgb(150,150,150, .5)'), name = "Casos")
p <- p %>% add_trace(x = casos_SP$date, y = casos_SP$ma5center, type = "scatter", 
              mode = "lines", line = list(color = 'rgb(235,12,24)', width = 2), 
              name = "MA 5cent") %>% 
  add_trace(x = casos_SP$date, y = casos_SP$ma5esq, type = "scatter", mode = "lines", 
            line = list(color = 'rgb(23,212,24)', width = 2), name = "MA 5esq") %>% 
  add_trace(x = casos_SP$date, y = casos_SP$ma5dir, type = "scatter", mode = "lines", 
            line = list(color = 'rgb(23,12,224)', width = 2), name = "MA 5dir") 
yax <- list(title = "Casos Dia (média móvel 5 dias)",
            separatethousands = TRUE,
            exponentformat = "none"
           )
p <- layout(p, yaxis = yax)
p

Um zoom na parte final do gráfico mostrando as médias móveis.

Zoom no gráfico das Médias Móveis - plotly

Veja como as médias móveis aparecem deslocadas nos gráficos; entretanto, como são calculadas com os mesmos números (mesma janela), são exatamente iguais.

That’s all folks!

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".

Citation

For attribution, please cite this work as

Menezes (2021, Sept. 25). Tips to Share and Grow: Médias Móveis. Retrieved from https://momenezes.github.io/tutorials/posts/2021-09-25-mediasmoveis/

BibTeX citation

@misc{menezes2021médias,
  author = {Menezes, Mario O. de},
  title = {Tips to Share and Grow: Médias Móveis},
  url = {https://momenezes.github.io/tutorials/posts/2021-09-25-mediasmoveis/},
  year = {2021}
}