Conceitos, cálculos e visualização.
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.
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
).
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 é:
frollmean(x, n = w, align = "left|center|right")
x
é o elemento (vetor) para o qual vamos calcular a média móvel;n
é a largura da janela, o nosso \(w\) na fórmula mostrada anteriormente;align
é o alinhamento, um de “left”, “center” ou “right”.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
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
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>
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
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
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
Um zoom na parte final do gráfico mostrando as médias móveis.
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.
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!
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 ...".
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} }