Category

Data Science

Como extrair componentes de tendência e sazonalidade de uma série temporal

By | Data Science

Tendência e sazonalidade são os componentes não observáveis de uma série temporal que representam, respectivamente, o movimento de longo prazo e o padrão regular (queda/subida) de um determinado período da série de tempo. A extração desses componentes pode ser feita facilmente no R usando a decomposição STL, método desenvolvido por Cleveland et al. (1990).

Algumas vantagens desse método em relação aos métodos clássicos de decomposição, como SEATS e X-11, são:

  • Ao contrário do SEATS e do X-11, a decomposição STL lida com qualquer tipo de sazonalidade, não apenas dados mensais e trimestrais;
  • O componente sazonal pode variar ao longo do tempo e a taxa de mudança pode ser definida pelo usuário;
  • A suavidade do componente tendência-ciclo também pode ser controlada pelo usuário;
  • É robusto em caso de outliers (ou seja, pode ser especificado uma decomposição robusta), de modo que observações incomuns não afetem as estimativas dos componentes, com exceção da série "restante".

Em se tratando de séries de tempo econômicas, parece ser uma ótima opção para diversos contextos, dado que a grande maioria das séries foram afetadas pela pandemia da Covid-19 (além de outros choques usuais no caso da economia brasileira).

Destaca-se ainda que o procedimento pode ser feito de maneira completamente automatizada, graças ao belo trabalho da família de pacotes tidyverts.

Exemplo no R

Abaixo aplicamos a decomposição STL sobre a série temporal que traz a popularidade do termo de busca "vagas de emprego" no Google. É esperado que a série apresente de forma clara um padrão sazonal, dado o impulso frequente de contratações de festas de fim de ano.


# Pacotes -----------------------------------------------------------------

# Carregar pacotes utilizados
library(magrittr)
library(dplyr)
library(gtrendsR)
library(tsibble)
library(fabletools)
library(feasts)
library(ggplot2)

# Coleta de dados ---------------------------------------------------------

# Primeiro coletamos os dados de exemplo provenientes do Google Trends
# de forma online usando API com o pacote gtrendsR

# Termo de busca "vagas de emprego" no Google; índice de 0 a 100 representa
# a popularidade relativa ao longo do tempo
df_vagas <- gtrendsR::gtrends(
keyword = "vagas de emprego",
geo = "BR",
time = "all",
onlyInterest = TRUE
)

# Exibir classe do objeto
class(df_vagas)

# Tratamento de dados -----------------------------------------------------

# Em seguida realizamos alguns tratamentos, selecionando e convertendo as
# colunas, além de transformar o objeto para classe tsibble
vagas <- df_vagas %>%
magrittr::extract2(1) %>%
dplyr::mutate(
date = tsibble::yearmonth(date),
hits = as.numeric(hits),
.keep = "used"
) %>%
tsibble::as_tsibble(index = date)

# Exibindo as primeiras linhas
vagas

# Extrair componentes: sazonalidade e tendência ---------------------------

# Aplica modelo decomposição da série (STL decomposition) e transforma
# resultado para um objeto tabular de classe "dable"
componentes <- vagas %>%
fabletools::model(feasts::STL(hits, robust = TRUE)) %>%
fabletools::components()

# Exibir resultado
componentes

# Plotar resultado
fabletools::autoplot(componentes) +
ggplot2::labs(
title = 'Decomposição STL: termo "vagas de emprego" no Google',
x = NULL,
caption = "Dados: Google | Elaboração: analisemacro.com.br"
)

Os gráficos empilhados acima mostram, em primeiro, a série original do Google Trends, seguida abaixo pelos componentes de tendência e sazonalidade identificados automaticamente pelo método STL, além da série "restante" que informa a variação restante dos dados não identificada como sazonal ou tendencial.

Consulte a documentação de feasts::STL para detalhes sobre especificação dos parâmetros e opções.

Referências

R. B. Cleveland, W. S. Cleveland, J.E. McRae, and I. Terpenning (1990) STL: A Seasonal-Trend Decomposition Procedure Based on Loess. Journal of Official Statistics, 6, 3–73.

Hyndman, R.J., & Athanasopoulos, G. (2021) Forecasting: principles and practice, 3rd edition, OTexts: Melbourne, Australia. OTexts.com/fpp3. Accessed on <2021-12-02>.

 

Hackeando o R: agrupando gráficos no R

By | Hackeando o R

Uma das etapas mais importante da análise de dados é a apresentação visual. Sabe-se que tanto para quem necessita tirar conclusões a partir dos dados, e também para ouvintes de outros segmentos, a parte visual demonstra-se como essencial para o entendimento do tópico que está sendo discutido. No Hackeando o R de hoje, iremos mostrar como podemos encaixar gráficos de forma que se tenha uma apresentação amigável, simples e rápida, combinando gráficos em apenas uma única figura.

O pacote mais importante no R para a visualização de dados, como todos sabem, é o pacote {ggplot2}. Apesar de suas inumeráveis funcionalidades, alguns pacotes o ajudam a potencializar seu uso. Como mostraremos, os pacotes {patchwork} e o {gridExtra} o ajudam na tarefa especifica de combinar múltiplos gráficos.

library(gridExtra)
library(patchwork)
library(tidyverse)

Para começarmos com os exemplos, primeiro devemos atribuir a um objeto um gráfico feito a partir do {ggplot2}. Utilizaremos o dataset Economics como exemplo, criando três gráficos diferentes.

# Gráfico de linha

psav_line <- economics %>% 
  ggplot(aes(x = date, y = psavert))+
  geom_line()+
  theme_minimal()+
  labs(x = "",
       y = "",
       title = "Personal savings rate - USA")

# Histograma

psav_des <- economics %>% 
  ggplot(aes(psavert))+
  geom_density(binwidth = .1, 
                 fill = "darkblue",
                 colour = "black")+
  theme_minimal()+
  labs(x = "",
       y = "",
       title = "Personal savings rate - USA")

# Gráfico de linha

pce_line <- economics %>% 
  ggplot(aes(x = date, y = pce))+
  geom_line()+
  theme_minimal()+
  labs(x = "",
       y = "",
       title = "Personal consumption expenditures",
       subtitle = "in billions of dollars - USA")

Salvado nossos gráficos, podemos utilizar o pacote {patchwork}, no qual funciona utilizando operadores matemáticos. O "+" é utilizado para deixar os gráficos lado a lado, como uma coluna. O uso de "()" serve para agrupar os gráficos e o "/" para empilhar um em outro.

pce_line + (psav_line / psav_des)+
  plot_annotation(
    title = "Economics Dataset")

Veja como podemos mudar a orientação dos gráficos mudando os operadores:

pce_line + psav_line + psav_des +
  plot_annotation(
    title = "Economics Dataset")

Outro pacote que pode ajudar na combinação de gráficos é o {gridExtra}, que diferentemente do {patchwork}, utiliza-se a função grid.arrange para ordernar os gráficos.

Veja que por padrão, a função empilha os gráficos, como se fosse em formato de linhas.


grid.arrange(psav_line, psav_des)

Também pode se especificar para que sejam ordenados em formato de colunas, podendo também escolher quantas queira.


grid.arrange(pce_line, psav_line, psav_des, ncol= 3)

(*) Quer aprender mais sobre a linguagem R e como construir gráficos? confira nosso Curso de Introdução ao R para análise de dados.

________________________

Hackeando o R: construindo gráficos com resultados estatísticos

By | Hackeando o R

Nesse post do Hackeando o R, iremos dar uma olhada em um pacote bem interessante que pode ajudar na criação de gráficos com propriedades estatísticas, de forma que a análise visual se torne mais simples e rápida.

O pacote {ggstatsplot} facilita não só a criação, bem como ajuda a sumarizar resultados estatísticos dentro dos próprios gráficos pro usuário.

Iremos utilizar como exemplo nesse post dados referentes aos retornos mensais de três ativos financeiros: PETR4, ITUB4 e ABEV3, além também dos retornos mensais do índice ibovespa. Caso tenha interesse em aprender a como obter esses dados, veja nosso post sobre.

Vamos utilizar os dados da Ibovespa para visualizar o histograma. Veja que o pacote insere uma expressão indicando a média dos retornos, em conjunto com uma linha tracejada. Também é retornado um linha com resultados sobre t-test, p-value, intervalo de confiança, tamanho de efeito, além do número de observações.

# Histograma
gghistostats(
  data = ibov_returns,
  x = `Ibovespa`,
  bindwidth = 1,
  normal.curve = TRUE,
  normal.curve.args = list(color = "red", size = 0.7)
)

Caso tenha um conjunto de dados com diversas variáveis, é possível gerar um gráficos com todas em conjunto.

# Histogramas agrupados

grouped_gghistostats(
  data = asset_returns_long,
  x = returns,
  grouping.var = assets,
  bindwidth = 1,
  normal.curve = TRUE,
  normal.curve.args = list(color = "red", size = 0.7),
  plotgrid.args = list(nrow = 2)
)

Além de um único histograma, é possível também gerar um gráfico de dispersão com uma reta de regressão, além do respectivo histograma de cada variável.

# Gráfico de dispersão com linha de regressão e Histograma

ggscatterstats(
  data = all_returns,
  x = `Ibovespa`,
  y = `ITUB4`
)

Também é possível criar uma matriz de correlação.

# Gráfico de correlação

ggcorrmat(
  data = all_returns,
  colors = c("#B2182B", "white", "#4D4D4D"),
  title = "",
  subtitle = ""
)

O pacote trabalha também com conjunto de dados de outras classes, não só numéricos, utilizando uma estatística apropriada para cada. Além de diversos outros gráficos.

________________________
(*) Para entender mais sobre análises estatísticas, confira nosso Curso de Estatística usando R e Python.

________________________

Séries temporais: detectando mudança de média no R

By | Data Science

Ao analisar séries temporais pode ser útil identificar pontos de mudança em seu comportamento, utilizando métodos de detecção para tal. Existem diversos métodos e algoritmos para implementar esse tipo de análise, desde simples cálculos envolvendo erro quadrático médio até abordagens Bayesianas. Neste texto mostramos uma maneira simples de detectar pontos de mudança em uma série temporal com o método de Taylor (2000).

Metodologia

O método desenvolvido por Taylor (2000), conforme mencionado, se baseia em um cálculo simples de erro quadrático médio (EQM) para identificar quando uma mudança na série ocorreu. A ideia geral é separar a série temporal em segmentos e calcular o EQM dos mesmos para identificar pontos de mudança, considerando o valor que minimiza o EQM. Formalmente:

onde:

Exemplo no R

A implementação do método de detecção de pontos de mudança de média, desenvolvido por Taylor (2000), é feita recursivamente pelo pacote ChangePointTaylor no R.

Neste exemplo aplicamos o método para a série anual da Produtividade total dos fatores da economia brasileira, variável disponível no dataset da Penn World Table 10.0.


# Pacotes -----------------------------------------------------------------

library(ChangePointTaylor)
library(pwt10)
library(dplyr)
library(tidyr)
library(ggplot2)
library(scales)
library(ggtext)

# Dados -------------------------------------------------------------------

# Tibble com dados da Produtividade total dos fatores - Brasil (2017 = 1)
tfp_br <- pwt10::pwt10.0 %>%
dplyr::filter(isocode == "BRA") %>%
dplyr::select(.data$year, .data$rtfpna) %>%
tidyr::drop_na() %>%
dplyr::as_tibble()

tfp_br

# Aplicar método de detecção de mudança (Taylor, 2000) --------------------

# Informar vetor de valores da série e
# vetor de nomes (usalmente a data correspondente ao valor)
change_points <- ChangePointTaylor::change_point_analyzer(
x = tfp_br$rtfpna,
labels = tfp_br$year
)

dplyr::as_tibble(change_points)

# Visualização de resultados ----------------------------------------------

# Gera gráfico ggplot2
tfp_br %>%
ggplot2::ggplot(ggplot2::aes(x = year, y = rtfpna)) +
ggplot2::geom_line(size = 2, color = "#282f6b") +
ggplot2::geom_vline(
xintercept = change_points$label,
color = "#b22200",
linetype = "dashed",
size = 1
) +
ggplot2::scale_x_continuous(breaks = scales::extended_breaks(n = 20)) +
ggplot2::scale_y_continuous(labels = scales::label_number(decimal.mark = ",", accuracy = 0.1)) +
ggplot2::labs(
title = "Produtividade Total dos Fatores - Brasil",
subtitle = "Preços nacionais constantes (2017 = 1)<br>Linhas tracejadas indicam pontos de mudança de média (Taylor, 2000)",
y = "PTF",
x = NULL,
caption = "**Dados**: Penn World Table 10.0 | **Elaboração**: analisemacro.com.br"
) +
ggplot2::theme_light() +
ggplot2::theme(
panel.grid = ggplot2::element_blank(),
axis.text = ggtext::element_markdown(size = 12, face = "bold"),
axis.title = ggtext::element_markdown(size = 12, face = "bold"),
plot.subtitle = ggtext::element_markdown(size = 16, hjust = 0),
plot.title = ggtext::element_markdown(
size = 30,
face = "bold",
colour = "#282f6b",
hjust = 0,
),
plot.caption = ggtext::element_textbox_simple(
size = 12,
colour = "grey20",
margin = ggplot2::margin(10, 5.5, 10, 5.5)
)
)

Referências

Taylor, W. A. (2000). Change-point analysis: a powerful new tool for detecting changes.

 

Hackeando o R: analisando modelos com o tidymodels

By | Hackeando o R

No Hackeando o R de hoje, vamos continuar nossa exposição do pacote tidymodels, a partir daonde paramos no nosso post de semana passada. Para resumir, o método básico, chamado de workflow, depende apenas de uma receita, que descreve o processamento de dados, e um parsnip, que descreve o modelo que queremos utilizar e seus parâmetros.

Após realizarmos os passos acima, podemos tentar verificar a qualidade do nosso modelo através da reamostragem. Vamos começar com um exemplo da qualidade de imagens de células, do pacote modeldata. Os dados possuem uma classificação, que indica se a observação é boa ou ruim para o objetivo final do estudo. Como a amostra total é muito grande para ser classificada manualmente, nosso trabalho é montar um modelo que preveja corretamente a classificação a partir de variáveis mensuráveis, dada a amostra.

library(modeldata)
library(tidymodels)

data(cells)

Para iniciarmos, devemos separar nossa amostra em uma partição de treinamento e teste. Isso é feito facilmente pela função initial_split(). Note que removemos a coluna case, que não é interessante para nós, diretamente dentro da função, com linguagem do tidyverse. Ademais, o argumento strata é importante: como temos muito mais dados ruins do que bons, uma partição aleatória poderia conter dados ruins demais no treino ou no teste, dificultando a estimação. Ao utilizar o argumento, garantimos que ambas as partes possuam proporções 'razoáveis' de cada classe.

set.seed(123)

cell_split <- initial_split(cells %>% select(-case),
strata = class)

cell_train <- training(cell_split)
cell_test <- testing(cell_split)

Para a modelagem, faremos um modelo de random forest. Não entraremos nos detalhes de seu funcionamento, pois já falamos sobre esse modelo em um post mais antigo. Dentro do ambiente do tidymodels, podemos facilmente criar a random forest usando o pacote ranger:

rf_mod =
rand_forest(trees = 1000) %>%
set_engine("ranger") %>%
set_mode("classification")

rf_fit =
rf_mod %>%
fit(class ~ ., data = cell_train)

Após treinar o modelo, podemos testar ele com as funções do pacote yardstick. Abaixo, calculamos a acurácia das previsões:

rf_testing_pred =
predict(rf_fit, cell_test) %>%
bind_cols(predict(rf_fit, cell_test, type = "prob")) %>%
bind_cols(cell_test %>% select(class))

rf_testing_pred %>%
accuracy(truth = class, .pred_class)

Como podemos ver, o modelo é razoável, porém pode melhorar. Para isso, vamos utilizar a reamostragem, fazendo validação cruzada. O método é simples: criamos os folds, geramos um novo workflow, e o informamos que é para fazer o fit sobre cada um dos folds.

folds = vfold_cv(cell_train, v = 10)

rf_wf =
workflow() %>%
add_model(rf_mod) %>%
add_formula(class ~ .)

rf_fit_rs =
rf_wf %>%
fit_resamples(folds)

Após isso, podemos utilizar a função collect_metrics() para verificar o resultado dos modelos sobre cada fold. O resultado mostra que nosso teste inicial acaba sendo sim um bom previsor.


collect_metrics(rf_fit_rs)

 .metric .estimator mean n std_err .config 
<chr> <chr> <dbl> <int> <dbl> <chr> 
1 accuracy binary 0.833 10 0.00971 Preprocessor1_Model1
2 roc_auc binary 0.906 10 0.00901 Preprocessor1_Model1

________________________
(*) Para entender mais sobre a linguagem R e suas ferramentas, confira nosso Curso de Introdução ao R para análise de dados.

Receba diretamente em seu e-mail gratuitamente nossas promoções especiais
e conteúdos exclusivos sobre Análise de Dados!

Assinar Gratuitamente
{"cart_token":"","hash":"","cart_data":""}