Vamos agora brincar de séries temporais.

Existem diversos pacotes utilizados em séries temporais.

Um problema que precisamos enfrentar com séries temporais é que como os dados têm uma ordem, precisamos de alguma forma ter essa ordem escrita na base.

Além disso, a ordem é pelo tempo, que é algo que tras informação por si só. Por exemplo, se estamos com uma série temporal de vendas, é natural pensar que certas épocas do ano vendam mais que outras, e que isso se repita ano a ano.

Por isso, uma base de dados de série temporal precisa saber lidar com essa natureza de dados.

Base de dados

Base R

Historicamente, isso era feito pela função ts(), que funciona assim:

set.seed(1)

# simulaçao de dados com um arima
dados <- data.frame(
  mes = 1:48,
  vendas = arima.sim(list(order = c(1,1,0), ar = 0.7), n = 48)[-1]
)

plot(dados)

dados_ts <- ts(dados)
# agora o eixo x não é mais o mês!
plot(dados_ts)

plot(dados_ts[,"vendas"])

Agora vamos definir uma periodicidade

dados_ts <- ts(
  dados, 
  start = c(2005, 6), # começa no mês 6 
  frequency = 12 # um ciclo a cada 12 observações (anual)
)

plot(dados_ts[,"vendas"])

Também funciona

dados_ts <- ts(
  dados, 
  start = c(2005, 6), # começa no mês 6 
  deltat = 1/12
)

plot(dados_ts[,"vendas"])

Versão ggplot, usando pacote forecast (veremos adiante)

forecast::autoplot(dados_ts[,"vendas"])
## Warning in register(): Can't find generic `scale_type` in package ggplot2 to
## register S3 method.
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo

xts

O {xts} é uma versão mais “parruda” do ts(), criado para resolver algumas dificuldades dos objetos. Ganhou muita popularidade nos entre 2000-2015 e é usado como base para uma série de modelos.

Atualmente, o xts não é mais necessário para trabalhar com séries temporais. No entanto, é muito comum encontrá-lo em códigos de modelagem mais “roots”, construídos por pessoas que aprenderam com base R.

dados_xts <- xts::as.xts(dados_ts)
plot(dados_xts[,"vendas"])

Obs: outro pacote que você encontrará por aí é o {zoo}, mas ele é tão esquisito que não vale a pena estudá-lo. Se você encontrar código que usa o zoo e precisar reproduzir, recomendo que estude as funções de forma individualizada. O {xts} é uma forma de melhorar o {zoo}.

tsibble

As tsibbles são a versão tidy das séries temporais, e também a versão séries temporais das amadas tibbles. Pegando o exemplo anterior, temos

tsibble::tsibble(
  mes = dados$mes,
  vendas = dados$vendas
)
## Error: Can't determine index and please specify argument `index`.

Isso significa precisamos passar um índice, obrigatoriamente. O {xts} faz isso modificando o objeto, enquanto que a tsibble faz isso com uma coluna

dados_tsibble <- tsibble::tsibble(
  mes = dados$mes,
  vendas = dados$vendas,
  index = mes
)
dados_tsibble
## # A tsibble: 48 x 2 [1]
##      mes vendas
##    <int>  <dbl>
##  1     1   1.43
##  2     2   3.02
##  3     3   5.05
##  4     4   7.26
##  5     5   8.88
##  6     6   8.02
##  7     7   8.04
##  8     8   8.00
##  9     9   7.81
## 10    10   6.21
## # … with 38 more rows

outra alternativa:

dados_tsibble <- dados %>% 
  tsibble::as_tibble(index = mes)

Para dar a periodicidade, modificamos a coluna que indexa os dados, similar ao que faz o xts, mas de forma mais explícita:

dados_tsibble <- dados %>% 
  dplyr::mutate(
    mes = tsibble::yearmonth(mes),
    # se o mes fosse uma data, isso seria mais facil
    mes = mes + 12*35 + 4 
  ) %>% 
  tsibble::as_tsibble(index = mes)

dados_tsibble
## # A tsibble: 48 x 2 [1M]
##         mes vendas
##       <mth>  <dbl>
##  1 2005 jun   1.43
##  2 2005 jul   3.02
##  3 2005 ago   5.05
##  4 2005 set   7.26
##  5 2005 out   8.88
##  6 2005 nov   8.02
##  7 2005 dez   8.04
##  8 2006 jan   8.00
##  9 2006 fev   7.81
## 10 2006 mar   6.21
## # … with 38 more rows

Finalmente, para plotar:

feasts::autoplot(dados_tsibble, vendas)

Estatísticas básicas

base R

decomposição

dec_sum <- decompose(dados_ts[,"vendas"])
dec_mult <- decompose(dados_ts[,"vendas"], "multiplicative")
plot(dec_sum)

plot(dec_mult)

acf(dados_ts[,"vendas"])

pacf(dados_ts[,"vendas"])

forecast

O pacote forecast é uma das ferramentas mais usadas no dia-a-dia de quem trabalha com séries temporais. Construído antes do tidymodels, trata-se de um pacote com diversos modelos para lidar com séries temporais, mas ainda fora do ambiente “tidy”. O livro-base para uso do forecast é o FPP2 (https://otexts.com/fpp2/). Atualmente, temos o FPP3 com alternativas “tidy”, mas isso não implica que o forecast cairá em desuso, pois ele é muito bom.

Por enquanto veremos só a parte descritiva. No próximo lab, trabalharemos com modelagem.

fit_ets <- forecast::ets(dados_ts[,"vendas"])
forecast::autoplot(fit_ets)

forecast::ggseasonplot(dados_ts[,"vendas"])

forecast::ggseasonplot(dados_ts[,"vendas"], polar = TRUE)

Mais exemplos no FPP2.

Autocorrelação

forecast::Acf(dados_ts[,"vendas"])

feasts

O feasts é o pacote atual para análise descritiva de séries temporais. Ele é descrito no FPP3 (https://otexts.com/fpp3/) e está alinhado com todos os princípios tidy.

Season plot

dados_tsibble %>% 
  feasts::gg_season(y = vendas)

dados_tsibble %>% 
  feasts::gg_season(y = vendas, polar = TRUE)

Mais exemplos no FPP3.

dados_tsibble %>% 
  feasts::ACF(vendas) %>% 
  feasts::autoplot()

dados_tsibble %>% 
  feasts::PACF(vendas) %>% 
  feasts::autoplot()

dados_tsibble %>% 
  feasts::gg_lag(vendas, geom = "point")

Para pegar os componentes de forma tidy:

dados_tsibble %>% 
  fabletools::model(feasts::STL(vendas)) %>% 
  fabletools::components()
## # A dable: 48 x 7 [1M]
## # Key:     .model [1]
## # :        vendas = trend + season_year + remainder
##    .model                   mes vendas trend season_year remainder season_adjust
##    <chr>                  <mth>  <dbl> <dbl>       <dbl>     <dbl>         <dbl>
##  1 feasts::STL(vendas) 2005 jun   1.43  5.48      -1.70     -2.35           3.13
##  2 feasts::STL(vendas) 2005 jul   3.02  5.59      -0.531    -2.04           3.55
##  3 feasts::STL(vendas) 2005 ago   5.05  5.69       0.353    -0.994          4.70
##  4 feasts::STL(vendas) 2005 set   7.26  5.80       0.743     0.713          6.51
##  5 feasts::STL(vendas) 2005 out   8.88  5.88       0.723     2.28           8.15
##  6 feasts::STL(vendas) 2005 nov   8.02  5.95       0.121     1.95           7.90
##  7 feasts::STL(vendas) 2005 dez   8.04  6.03       0.109     1.91           7.93
##  8 feasts::STL(vendas) 2006 jan   8.00  6.09       0.135     1.77           7.86
##  9 feasts::STL(vendas) 2006 fev   7.81  6.16       0.544     1.11           7.27
## 10 feasts::STL(vendas) 2006 mar   6.21  6.23       0.378    -0.396          5.83
## # … with 38 more rows

Exercícios

Link: https://otexts.com/fpp3/graphics-exercises.html Faça os exercícios 3, 8, 10, 12

Forecasts simples

pacote forecast

dados_ts_vendas <- dados_ts[,"vendas"]
media <- forecast::meanf(dados_ts_vendas, 5)
naive <- forecast::naive(dados_ts_vendas, 5)
seasonal_naive <- forecast::snaive(dados_ts_vendas, 5)
drift <- forecast::rwf(dados_ts_vendas, 5, drift = TRUE)
dados_ts_vendas %>% 
  forecast::autoplot() +
  forecast::autolayer(media, series = "Media", PI = FALSE) +
  forecast::autolayer(naive, series = "Naive", PI = FALSE) +
  forecast::autolayer(seasonal_naive, series = "SNaive", PI = FALSE) +
  forecast::autolayer(drift, series = "Drift", PI = FALSE)

pacote feasts

Média móvel

dados_tsibble %>%
  dplyr::mutate(ma_5 = slider::slide_dbl(
    vendas, 
    mean, 
    .before = 2, # janela antes 
    .after = 2,  # janela depois
    complete = TRUE # retorna um vetor com mesmo tamanho
  )) %>% 
  feasts::autoplot(vendas) +
  ggplot2::geom_line(ggplot2::aes(y = ma_5), colour = "#D55E00")

Modelos que vimos no forecast

dados_para_modelo <- dados_tsibble %>% 
  tsibble::filter_index("2005 jun" ~ "2008 dec")

modelos <- dados_para_modelo %>% 
  fabletools::model(
    mean = fable::MEAN(vendas),
    naive = fable::NAIVE(vendas),
    snaive = fable::SNAIVE(vendas),
    drift = fable::RW(vendas ~ drift()),
  ) %>% 
  fabletools::forecast(h = 5)

modelos %>% 
  feasts::autoplot(dados_para_modelo, level = NULL)