Séries Temporais com R: Análise Theta para o Consumo do Varejo em MS com pacotes `forecast::thetaf` e `forecTheta`
Licença
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
Citação
Sugestão de citação:
FIGUEIREDO, Adriano Marcos Rodrigues. Séries Temporais com R: Análise Theta para o Consumo do Varejo em MS com pacote forecast::thetaf
e forecTheta
. Campo Grande-MS,Brasil: RStudio/Rpubs, 2020. Disponível em http://rpubs.com/amrofi/varejoms_thetaf e em https://adrianofigueiredo.netlify.app/post/series-temporais-theta-consumo-varejo-ms/.
Script para reprodução (se utilizar, citar como acima)
Download 2020-04-22-séries-temporais-com-r-análise-theta-para-o-consumo-do-varejo-em-ms-com-pacote-forecast-thetaf-e-e-forectheta.RmdIntrodução
Neste arquivo utilizo a série do Índice de volume de vendas no varejo Total de Mato Grosso do Sul, série mensal a partir de jan/2000 até ago/2019 obtida com o pacote BETS
e importada do Banco Central do Brasil. Portanto, são 236 observações mensais.
Dados
Farei de duas formas para o leitor. Uma carrega direto do site do Banco Central do Brasil com o pacote BETS
(FERREIRA, SPERANZA e COSTA, 2018) e a outra eu gerei a estrutura idêntica pela função dput()
para os leitores que não conseguirem por qualquer motivo o acesso ao site do Banco Central (as vezes vejo isso ocorrer dependendo dos bloqueios da sua rede de internet). Esclareço ao leitor que após baixar a série pelo BETS, fiz o dput e a partir de então, desabilitei o bloco (Chunk
) que acessa o BETS apenas para agilizar os cálculos.
library(BETS)
# Pegando as séries a partir do site do Banco Central do Brasil
# Índice de volume de vendas no varejo Total de Mato Grosso do Sul
# mensal a partir de jan/2000 até ago/2019
# 236 observações mensais
varejoms <- BETSget(1479)
dput(varejoms) # opção para ter os dados como na structure abaixo
library(BETS)
varejoms <- structure(c(35.2, 35.6, 39.2, 40.5, 41.6, 40.4, 40.8, 38.7, 37.3, 37.6,
35.6, 47.4, 34.2, 32.2, 38, 37.5, 38.8, 35, 38.4, 40.2, 38.2, 39.3, 36, 46.3,
36.4, 34, 39, 37.8, 38.9, 35.3, 37.2, 38.1, 35.6, 38.3, 35.6, 45.7, 32.2, 31.6,
35.2, 36.8, 37.5, 34.8, 38.4, 38.1, 37, 39, 37.3, 49, 35.8, 35.3, 40.2, 41.3,
43.9, 41.6, 45.9, 42.3, 42.2, 44, 41.3, 56.9, 38.5, 38.5, 45.3, 43.6, 46.2, 44.3,
47.5, 46.5, 46.4, 46, 44.1, 61, 42, 40.2, 44.6, 44.5, 47.8, 45.3, 46.5, 48.5,
47.7, 50.2, 49.3, 64.5, 47, 46.8, 51, 50.5, 55, 51.3, 52.8, 55.3, 54.8, 55.6,
55.3, 72.2, 54.5, 52.1, 56.2, 57.2, 60.8, 56.1, 61.8, 61.6, 59.8, 63.3, 57.7,
77.4, 61.4, 51.9, 57.3, 57.9, 61.9, 57.3, 61.1, 61.1, 60.6, 65.6, 63.5, 83.1,
64.1, 60.2, 67.8, 67.1, 72.8, 68.5, 71.1, 69.3, 69.9, 71.1, 67.9, 92.7, 67.5,
64.8, 69.1, 69.4, 79.6, 70.2, 73.8, 72.5, 71.3, 75.6, 74.7, 100.8, 79.5, 75.7,
82.4, 78, 84.8, 83.2, 84.8, 88.5, 86.3, 91.7, 92.8, 111.4, 92.8, 83.7, 92.5,
88.3, 93.9, 88.8, 96, 95.9, 93.2, 98.3, 100.5, 128.8, 97.2, 90.2, 94.3, 94.4,
101.1, 92, 96.4, 98.2, 97.6, 105.8, 103.1, 129.6, 99.6, 87.8, 97, 94.8, 98.6,
93.4, 98.4, 96.4, 92.5, 100.6, 97.2, 124.5, 91.5, 85.1, 91.6, 88.5, 92.2, 87.4,
90.5, 88.1, 85.2, 89.4, 93.4, 116.9, 90.8, 84, 89.7, 86.3, 90, 87.3, 90.8, 93.5,
93.7, 91.4, 93.5, 114.1, 87.8, 81.1, 94.5, 83.2, 89.9, 88.8, 89.3, 93.7, 93.5,
96.3, 101.3, 118.3, 93.8, 85.2, 90, 86.6, 90, 85.2, 91, 94.1), .Tsp = c(2000,
2019.58333333333, 12), class = "ts")
print(varejoms)
FALSE Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
FALSE 2000 35.2 35.6 39.2 40.5 41.6 40.4 40.8 38.7 37.3 37.6 35.6 47.4
FALSE 2001 34.2 32.2 38.0 37.5 38.8 35.0 38.4 40.2 38.2 39.3 36.0 46.3
FALSE 2002 36.4 34.0 39.0 37.8 38.9 35.3 37.2 38.1 35.6 38.3 35.6 45.7
FALSE 2003 32.2 31.6 35.2 36.8 37.5 34.8 38.4 38.1 37.0 39.0 37.3 49.0
FALSE 2004 35.8 35.3 40.2 41.3 43.9 41.6 45.9 42.3 42.2 44.0 41.3 56.9
FALSE 2005 38.5 38.5 45.3 43.6 46.2 44.3 47.5 46.5 46.4 46.0 44.1 61.0
FALSE 2006 42.0 40.2 44.6 44.5 47.8 45.3 46.5 48.5 47.7 50.2 49.3 64.5
FALSE 2007 47.0 46.8 51.0 50.5 55.0 51.3 52.8 55.3 54.8 55.6 55.3 72.2
FALSE [ reached getOption("max.print") -- omitted 12 rows ]
class(varejoms)
FALSE [1] "ts"
# [1] 'ts'
A rotina de dados obtidos pelo BETS já retorna a série em formato ts
, ou seja, série temporal. Farei então a criação de uma série em diferenças para observar o comportamento da série em nível e em diferenças.
Inicialmente olharei as estatísticas descritivas da série. Em seguida farei um plot básico da série e o plot pelo pacote dygraphs
, útil para ver os pontos de picos e momentos específicos.
dvarejo <- diff(varejoms)
# estatisticas basicas
summary(varejoms)
Min. 1st Qu. Median Mean 3rd Qu. Max.
31.60 44.08 64.65 67.39 90.05 129.60
# plot basico
plot(varejoms)
# pelo pacote dygraph dá mais opções
library(dygraphs)
dygraph(varejoms, main = "Índice de volume de vendas no varejo total de Mato Grosso do Sul <br> (Mensal) (2011=100) BCB 1479") %>%
dyAxis("x", drawGrid = TRUE) %>% dyEvent("2005-1-01", "2005", labelLoc = "bottom") %>%
dyEvent("2015-1-01", "2015", labelLoc = "bottom") %>% dyEvent("2018-1-01", "2018",
labelLoc = "bottom") %>% dyEvent("2019-1-01", "2019", labelLoc = "bottom") %>%
dyOptions(drawPoints = TRUE, pointSize = 2)
É possivel visualizar nos plots acima: sazonalidade (por exemplo, picos em dezembro de cada ano); a tendência aparentemente crescente até 2014 e decresce com a “crise” brasileira; e uma aparente não-estacionariedade (média e variância mudam no tempo).
Análise da série
Função de Autocorrelação (FAC) e Autocorrelação parcial (FACp) com defasagem 36
Série em nível
Usarei a rotina do Hyndman e Athanasopoulos (2018).
varejo <- varejoms
varejo %>% forecast::ggtsdisplay(main = "Série de Varejo MS")
Neste caso, o ggtsdisplay
do pacote forecast
já retorna os gráficos da série, e respectivas ACF e PACF.
Série em primeira diferença
Como a série apresenta variações sazonais importantes, assim como tendência importante, claramente não-estacionárias, vou olhar também em primeira diferença.
varejo %>% diff() %>% forecast::ggtsdisplay(main = "Série varejo de MS em primeira diferença")
Primeira diferença sazonal e ACF e PACF
Farei agora a diferença sazonal.
varejo %>% diff(lag = 12) %>% forecast::ggtsdisplay(main = "Série varejo de MS em primeira diferença sazonal")
Ajuste sazonal e ACF e PACF
Aplicaremos o ajuste sazonal tipo STL (Seasonal Decomposition of Time Series by Loess) aos dados.
library(fpp2)
varejoadj <- varejo %>% stl(s.window = "periodic") %>% seasadj()
autoplot(varejoadj, main = "Série de Varejo MS com ajuste sazonal STL")
E agora os plots de ACF e PACF na série ajustada sazonalmente.
varejoadj %>% diff() %>% forecast::ggtsdisplay(main = "Série varejo de MS em primeira diferença e ajuste sazonal")
Método Theta pelo forecast::thetaf
y <- varejoms
h = 12
require(forecast)
T <- thetaf(y, h)$mean
autoplot(varejoms, series = "Varejo-MS") + autolayer(T, series = "Theta", PI = FALSE) +
xlab("Mês/Ano") + ylab("Índice (2011=100)") + ggtitle("Índice de volume de vendas no varejo total de Mato Grosso do Sul <br> (Mensal) - BCB 1479")
Ou pelo dygraphs, teremos:
library(dygraphs)
dygraph(cbind(varejoms, T), main = "Índice de volume de vendas no varejo total de Mato Grosso do Sul <br> (Mensal) (2011=100) BCB 1479") %>%
dyAxis("x", drawGrid = TRUE) %>% dyEvent("2005-1-01", "2005", labelLoc = "bottom") %>%
dyEvent("2015-1-01", "2015", labelLoc = "bottom") %>% dyEvent("2018-1-01", "2018",
labelLoc = "bottom") %>% dyEvent("2019-1-01", "2019", labelLoc = "bottom") %>%
dyOptions(drawPoints = TRUE, pointSize = 2)
Outros detalhes estão no objeto Theta.
modelo <- thetaf(y, h)
summary(modelo)
Forecast method: Theta
Model Information:
$alpha
[1] 0.6379929
$drift
X
0.1636578
$sigma
[1] 5.651715
$call
thetaf(y = y, h = h)
Error measures:
ME RMSE MAE MPE MAPE MASE
Training set 0.3545975 2.389965 1.818344 0.5126286 2.748774 0.3983852
ACF1
Training set -0.09309372
Forecasts:
Point Forecast Lo 80 Hi 80 Lo 95 Hi 95
Sep 2019 90.76717 87.72049 93.81384 86.10768 95.42666
Oct 2019 94.53450 90.92057 98.14842 89.00748 100.06151
Nov 2019 92.07228 87.96879 96.17577 85.79654 98.34802
Dec 2019 118.91229 114.37172 123.45287 111.96808 125.85650
Jan 2020 89.33067 84.39154 94.26980 81.77692 96.88442
Feb 2020 83.61381 78.30597 88.92165 75.49616 91.73146
Mar 2020 92.45136 86.79880 98.10392 83.80652 101.09620
Apr 2020 90.56873 84.59130 96.54615 81.42705 99.71041
May 2020 96.09921 89.81369 102.38473 86.48634 105.71209
Jun 2020 89.79625 83.21704 96.37546 79.73422 99.85828
Jul 2020 94.82093 87.96059 101.68126 84.32895 105.31290
Aug 2020 94.79960 87.66922 101.92999 83.89462 105.70458
autoplot(modelo, PI = TRUE)
knitr::kable(modelo)
Point Forecast | Lo 80 | Hi 80 | Lo 95 | Hi 95 | |
---|---|---|---|---|---|
Sep 2019 | 90.76717 | 87.72049 | 93.81384 | 86.10768 | 95.42666 |
Oct 2019 | 94.53450 | 90.92057 | 98.14842 | 89.00748 | 100.06151 |
Nov 2019 | 92.07228 | 87.96879 | 96.17577 | 85.79654 | 98.34802 |
Dec 2019 | 118.91229 | 114.37172 | 123.45287 | 111.96808 | 125.85650 |
Jan 2020 | 89.33067 | 84.39154 | 94.26980 | 81.77692 | 96.88442 |
Feb 2020 | 83.61381 | 78.30597 | 88.92165 | 75.49616 | 91.73146 |
Mar 2020 | 92.45136 | 86.79880 | 98.10392 | 83.80652 | 101.09620 |
Apr 2020 | 90.56873 | 84.59130 | 96.54615 | 81.42705 | 99.71041 |
May 2020 | 96.09921 | 89.81369 | 102.38473 | 86.48634 | 105.71209 |
Jun 2020 | 89.79625 | 83.21704 | 96.37546 | 79.73422 | 99.85828 |
Jul 2020 | 94.82093 | 87.96059 | 101.68126 | 84.32895 | 105.31290 |
Aug 2020 | 94.79960 | 87.66922 | 101.92999 | 83.89462 | 105.70458 |
Método Theta pelo forecTheta
de Fiorucci et al (2016)
library(forecTheta)
y <- varejoms
h = 12
set.seed(12345)
mod2 <- dotm(y, h)
plot(mod2)
(mod2)
Forecast method: Dynamic Optimised Theta Model
Seasonal decomposition type: multiplicative
Optimisation method: Nelder-Mead
Number of theta lines: 2
Weights for theta lines:
Estimative
omega_1 0.48
omega_2 0.52
Estimative of parameters:
MLE
ell0 15.61
alpha 0.62
theta 1.92
Forecasting points and prediction intervals
Mean Lo 80 Hi 80 Lo 90 Hi 90 Lo 95 Hi 95
Sep 2019 90.7055 87.7358 94.3555 87.0361 95.0432 86.5322 95.7098
Oct 2019 94.4625 91.2530 98.5915 90.4380 99.4901 89.5612 100.3729
Nov 2019 91.9939 87.9531 96.3013 87.0091 97.6981 86.1153 98.2929
Dec 2019 118.7997 113.5964 125.0013 112.1571 126.6257 111.3828 127.9087
Jan 2020 89.2369 84.7963 94.2359 83.4705 95.0678 82.5591 96.2033
Feb 2020 83.5169 78.5097 88.5590 77.4747 89.7529 76.9382 91.4349
Mar 2020 92.3336 86.7244 98.2125 85.8621 99.3112 83.9983 100.0960
Apr 2020 90.4424 85.1185 96.1328 83.1143 97.9635 82.2356 98.6804
May 2020 95.9529 89.7126 102.5335 88.8577 103.9769 85.8770 104.7699
Jun 2020 89.6476 83.1236 96.1505 81.8708 97.2885 80.7374 98.5336
Jul 2020 94.6507 87.0673 101.6476 85.5549 103.3302 84.9208 104.3466
Aug 2020 94.6157 86.7363 101.6285 85.6061 103.3821 85.0348 104.6449
Warning: According with the Shapiro-Wilk test with 97% of confidence, the unseasoned residuals do not follow the Normal distribution. The prediction intervals may not be adequate.
Ou pelo dygraphs, teremos:
library(dygraphs)
require(forecast)
set.seed(12345)
T2 <- dotm(y, h)$mean
dygraph(cbind(varejoms, T2), main = "Índice de volume de vendas no varejo total de Mato Grosso do Sul <br> (Mensal) (2011=100) BCB 1479") %>%
dyAxis("x", drawGrid = TRUE) %>% dyEvent("2005-1-01", "2005", labelLoc = "bottom") %>%
dyEvent("2015-1-01", "2015", labelLoc = "bottom") %>% dyEvent("2018-1-01", "2018",
labelLoc = "bottom") %>% dyEvent("2019-1-01", "2019", labelLoc = "bottom") %>%
dyOptions(drawPoints = TRUE, pointSize = 2)
Parâmetro theta estimado:
mod2$par[2] # alpha
[1] 0.6234402
mod2$par[3] # theta
[1] 1.921107
Pesos estimados:
mod2$weights
Estimative
omega_1 0.4794667
omega_2 0.5205333
Valores iniciais dos thetas: 0,5 e 2. Opções para Método de otimização: ‘Nelder-Mead’, ‘L-BFGS-B’, ‘SANN’. O padrão é ‘Nelder-Mead’.
mod2$opt.method
[1] "Nelder-Mead"
Comparação com dados recentes
Agora que já temos as informações até fev/2020, podemos comparar as estimativas com os dados reais. Faremos a comparação relativamente ao forecast do forecast::thetaf
.
# dadosnovos<-BETS::BETSget(1479)
dadosnovos <- structure(c(35.2, 35.6, 39.2, 40.5, 41.6, 40.4, 40.8, 38.7, 37.3, 37.6,
35.6, 47.4, 34.2, 32.2, 38, 37.5, 38.8, 35, 38.4, 40.2, 38.2, 39.3, 36, 46.3,
36.4, 34, 39, 37.8, 38.9, 35.3, 37.2, 38.1, 35.6, 38.3, 35.6, 45.7, 32.2, 31.6,
35.2, 36.8, 37.5, 34.8, 38.4, 38.1, 37, 39, 37.3, 49, 35.8, 35.3, 40.2, 41.3,
43.9, 41.6, 45.9, 42.3, 42.2, 44, 41.3, 56.9, 38.5, 38.5, 45.3, 43.6, 46.2, 44.3,
47.5, 46.5, 46.4, 46, 44.1, 61, 42, 40.2, 44.6, 44.5, 47.8, 45.3, 46.5, 48.5,
47.7, 50.2, 49.3, 64.5, 47, 46.8, 51, 50.5, 55, 51.3, 52.8, 55.3, 54.8, 55.6,
55.3, 72.2, 54.5, 52.1, 56.2, 57.2, 60.8, 56.1, 61.8, 61.6, 59.8, 63.3, 57.7,
77.4, 61.4, 51.9, 57.3, 57.9, 61.9, 57.3, 61.1, 61.1, 60.6, 65.6, 63.5, 83.1,
64.1, 60.2, 67.8, 67.1, 72.8, 68.5, 71.1, 69.3, 69.9, 71.1, 67.9, 92.7, 67.5,
64.8, 69.1, 69.4, 79.6, 70.2, 73.8, 72.5, 71.3, 75.6, 74.7, 100.8, 79.5, 75.7,
82.4, 78, 84.8, 83.2, 84.8, 88.5, 86.3, 91.7, 92.8, 111.4, 92.8, 83.7, 92.5,
88.3, 93.9, 88.8, 96, 95.9, 93.2, 98.3, 100.5, 128.8, 97.2, 90.2, 94.3, 94.4,
101.1, 92, 96.4, 98.2, 97.6, 105.8, 103.1, 129.6, 99.6, 87.8, 97, 94.8, 98.6,
93.4, 98.4, 96.4, 92.5, 100.6, 97.2, 124.5, 91.5, 85.1, 91.6, 88.5, 92.2, 87.4,
90.5, 88.1, 85.2, 89.4, 93.4, 116.9, 90.8, 84, 89.7, 86.3, 90, 87.3, 90.8, 93.5,
93.7, 91.4, 93.5, 114.1, 87.8, 81.1, 94.5, 83.2, 89.9, 88.8, 89.3, 93.7, 93.5,
96.3, 101.3, 118.3, 93.8, 85.2, 90, 86.6, 90, 85.2, 91, 94.4, 93.4, 95.9, 102.6,
116, 94.9, 89.1), .Tsp = c(2000, 2020.08333333333, 12), class = "ts")
# View(cbind.zoo(data.fcst,dadosnovos))
require(zoo)
print(cbind.zoo(T, dadosnovos)[230:242])
T dadosnovos
fev 2019 NA 85.2
mar 2019 NA 90.0
abr 2019 NA 86.6
mai 2019 NA 90.0
jun 2019 NA 85.2
jul 2019 NA 91.0
ago 2019 NA 94.4
set 2019 90.76717 93.4
out 2019 94.53450 95.9
nov 2019 92.07228 102.6
dez 2019 118.91229 116.0
jan 2020 89.33067 94.9
fev 2020 83.61381 89.1
Acurácia do período Setembro/2019 a fev/2020:
# pelo forecast::thetaf T <- thetaf(y, h)$mean
previsto <- T
observado <- dadosnovos[237:242]
forecast::accuracy(previsto, observado)
ME RMSE MAE MPE MAPE
Test set 3.778214 5.615847 4.748978 4.003178 4.840044
Ou seja, um erro percentual médio de \(4.00\)% e um erro absoluto médio de \(\approx4.75\)%.
Comparação com o forecTheta::dotm
As estimativas para o forecTheta::dotm
foram obtidas fazendo T2<- dotm(y,h)$mean
. Da mesma forma, obtemos a acurácia do período Setembro/2019 a fev/2020.
# pelo forecTheta::dotm T2<- dotm(y,h)$mean
previsto2 <- T2
observado <- dadosnovos[237:242]
forecast::accuracy(previsto2, observado)
ME RMSE MAE MPE MAPE
Test set 3.864104 5.670028 4.797325 4.090202 4.894704
Ou seja, um erro percentual médio de \(4.09\)% e um erro absoluto médio de \(\approx4.80\)%.
Referências
ASSIMAKOPOULOS, V. and NIKOLOPOULOS, K. (2000). The theta model: a decomposition approach to forecasting. International Journal of Forecasting, 16, 521-530. DOI: https://doi.org/10.1016/S0169-2070(00)00066-2
FERREIRA, Pedro Costa; SPERANZA, Talitha; COSTA, Jonatha. (2018). BETS: Brazilian Economic Time Series. R package version 0.4.9. Disponível em: https://CRAN.R-project.org/package=BETS.
FIORUCCI, Jose Augusto; LOUZADA, Francisco Louzada; YIQI, Bao. (2016). forecTheta: Forecasting Time Series by Theta Models. R package version 2.2. Disponível em: https://CRAN.R-project.org/package=forecTheta.
HYNDMAN, Rob J. (2018a). fpp2: Data for “Forecasting: Principles and Practice” (2nd Edition). R package version 2.3. Disponível em: https://CRAN.R-project.org/package=fpp2.
HYNDMAN, R.J., & ATHANASOPOULOS, G. (2018) Forecasting: principles and practice, 2nd edition, OTexts: Melbourne, Australia. Disponível em: https://otexts.com/fpp2/. Accessed on 12 Set 2019.