Category

Data Science

Hackeando o R: criando temas no ggplot2

By | Hackeando o R

Quando o assunto é visualização de dados no R, é quase impossível não se lembrar do {ggplot2}. O pacote  se tornou quase que padrão na comunidade, e isso não foi ao acaso, de fato ele realmente é um dos melhores no sentido de criar gráficos seja de quaisquer tipos, sendo simples e flexível. No Hackeando o R de hoje ensinaremos alguns pontos básicos sobre como personalizar seu próprio tema com o {ggplot2}.

Antes de tudo, é importante saber alguns conceitos do pacote. Para sua utilização, é necessário especificar na função ggplot() o  data frame que irá ser utilizado, e também mapear os eixos x e y com a função aes(), de acordo com as colunas do conjunto de dados.

library(ggplot2)
ggplot(economics, aes(x = date, y = pce))

Porém, somente essa parte da função não é suficiente, portanto,  ele se divide em "subfunções", cada qual com seu respectivo propósito para a construção dos gráficos. São eles:

  • layer: coleção de elementos geométricos que formam os desenhos dos gráficos, são conhecidos pelas funções que iniciam com geom_ ou stats_.
  • scale: funciona como forma de alterar as escalas do gráfico em consonância com o espaço mapeado pelos valores que são inseridos.  Iniciam com scale_
  • coord: descreve como os dados coordenando se inserem no plano do gráfico, por padrão segue o cartesiano, no qual os valores de x e y se combinam. Iniciam com coord_
  • facet:  utilizada para criar diversos gráficos com base em diferentes categorias do dataset. Iniciam com facet_
  • theme: controla as cores, fontes, linhas e entre outros. Em suma, toda a parte visual do gráfico e que não faz parte dos dados. São criados com a função theme().

Dito isto, focaremos na estrutura da montagem de temas com o theme, que se separam em três subclasses: text, line e rectangle, cada uma com o proposito de alterar os elementos visuais do gráfico. Para cada subclasse existe um argumento específico de mudança e uma função padrão em que é utilizado para mudar as cores, fontes, tamanhos e entre outros. Vamos ver detalhadamente para cada tipo.

A primeira é o text, que controla toda a parte de texto do gráfico. Dentro da função themes(), é possível mudar desde todos os textos do gráfico com o argumento text =, e também é possível ser mais especificar, por exemplo, utilizando o argumento title =, em que é mudado apenas o texto do título.

Para realizar as mudanças, é necessário que após especificar o argumento do texto, para realizar as mudanças, é necessário utilizar a função element_text(). Exemplo:

ggplot(economics, aes(x = date, y = pce))+
geom_line(size = .8, colour = "darkblue")+
theme(title = element_text(color = "blue"))

Vemos a mudança no título do texto. Abaixo, segue os possíveis argumentos que podem ser utilizados para realizar as mudanças.

theme(
text,
 axis.title,
   axis.title.x,
      axis.title.x.top,
      axis.title.x.bottom,
    axis.title.y,
       axis.title.y.left,
       axis.title.y.right,
  title,
     legend.title,
     plot.title,
     plot.subtitle,
     plot.caption,
     plot.tag,
  axis.text,
   axis.text.x,
    axis.text.x.top,
    axis.text.x.bottom,
   axis.text.y,
    axis.text.y.left,
    axis.text.y.right,
legend.text,
strip.text,
   strip.text.x,
   strip.text.y)

O tipo line controla toda a parte de linhas dentro do plano do gráfico. Também é controlada a partir de argumentos próprios, com seus respectivos propósitos, além de possuir a sua própria função, chamada de element_line(). Exemplo:

ggplot(economics, aes(x = date, y = pce))+
geom_line(size = .8, colour = "darkblue")+
theme(axis.line = element_line(color = "blue"))

Abaixo, os argumentos próprios do tipo line.
theme(
line,
    axis.ticks,
      axis.ticks.x,
        axis.ticks.x.top,
        axis.ticks.x.bottom,
      axis.ticks.y,
       axis.ticks.y.left,
       axis.ticks.y.right,
    axis.line,
       axis.line.x,
         axis.line.x.top,
         axis.line.x.bottom,
       axis.line.y,
          axis.line.y.left,
          axis.line.y.right,
    panel.grid,
        panel.grid.major,
           panel.grid.major.x,
           panel.grid.major.y,
        panel.grid.minor,
           panel.grid.minor.x,
           panel.grid.minor.y)

Outro tipo é o rectangle, que altera toda a parte retangular dentro e fora do plano, além de alterar o retângulo que se encontra na legenda. Possui também seus próprios argumentos e sua função chamada element_rect(). Exemplo:

ggplot(economics, aes(x = date, y = pce))+
geom_line(size = .8, colour = "darkblue")+
theme(panel.background = element_rect(color = "blue"))
Abaixo, seguem os argumentos do tipo rect.
theme(
rect,
     legend.background,
     legend.key,
     legend.box.background,
     panel.background,
     panel.border,
     plot.background,
     strip.background,
        strip.background.x,
        strip.background.y)
Por fim, temos a função element_blank(), que pode ser utilizada pelos argumentos de todos os tipos com o propósito de "apagar" os elementos de interesse.
ggplot(economics, aes(x = date, y = pce))+
geom_line(size = .8, colour = "darkblue")+
theme(text = element_blank(),
line = element_blank(),
rect = element_blank())

É possível que seja criado um tema padrão, que pode ser salvo dentro de um objeto com a finalidade de ser reutilizado de forma rápida ao longo do código.

theme_economics <- theme(text = element_text(family = "sans", size = 14),
rect = element_blank(),
panel.grid = element_blank(),
title = element_text(color = "darkblue"),
axis.line = element_line(color = "black"))
Por fim, reutilizamos
ggplot(economics, aes(x = date, y = pce))+
geom_line(size = .8, colour = "darkblue")+
theme_economics

Viu como é fácil criar o próprio tema e sempre poder reutilizado? Caso queira se aprofundar em visualização de dados no R utilizando o pacote {ggplot2}, veja nosso Curso de gráficos com ggplot2.

Gerando previsões desagregadas de séries temporais

By | Data Science

Frequentemente, séries temporais podem ser desagregadas em vários atributos de interesse. Por exemplo1, o número total de veículos produzidos no país ao longo do tempo pode ser dividido em veículos comerciais leves, caminhões, ônibus, etc. Cada uma dessas categorias pode ainda ser desagregada em outros níveis, por regiões, por fabricante, etc., caracterizando o que pode ser chamado de "séries temporais hierárquicas".

Essa riqueza de informação e dados possibilita (e pode ser de interesse) gerar previsões desagregadas das séries, de modo que os pontos de previsão das séries desagregadas possam ser analisados individualmente e que, quando agregados de alguma forma, sejam coerentes com os valores agregados da série.

De modo geral, podemos representar o exemplo como:

Ou seja, para qualquer observação no tempo t, as observações no nível inferior da hierarquia serão agregadas para formar as observações da série acima.

Previsão hierárquica

Existem várias abordagens para gerar previsões hierárquicas com séries temporais, a mais comum e intuitiva é a bottom-up (de baixo para cima), onde primeiro geramos as previsões para cada série no nível inferior e, em seguida, somamos os pontos de previsão para obter previsões da série acima.

Por outro lado, a abordagem top-down (de cima para baixo) envolve primeiro a geração de previsões para a série agregada e, em seguida, desagregá-la na hierarquia utilizando proporções (geralmente baseadas na série histórica).

Ainda existem outras abordagens como a do Minimum Trace e suas variantes, sendo que cada uma tem seus prós e contras. Para se aprofundar no tema veja Forecasting: principles and practice de Hyndman, R.J., & Athanasopoulos, G. (2021), que apresenta detalhes sobre as abordagens disponíveis.

Exemplo: dados de produção da ANFAVEA

Mensalmente a ANFAVEA disponibiliza séries temporais da produção, licenciamento, exportação, etc. de veículos. Os dados são desagregados pelas categorias citadas acima e neste exemplo iremos explorar alguns métodos de gerar modelos de previsão para as séries de produção de veículos.

Primeiro, para reproduzir o código certifique-se de que tenha os seguintes pacotes em sua instalação do R:

# Carregar pacotes/dependências
library(magrittr)
library(GetBCBData)
library(dplyr)
library(tsibble)
library(fabletools)
library(ggplot2)
library(lubridate)
library(fable)

Para importar as séries podemos usar o banco de dados do Banco Central (BCB) através do pacote GetBCBData, bastando apontar os códigos de coleta obtidos diretamente no site da instituição.

raw_anfavea <- GetBCBData::gbcbd_get_series(
id = c(
"Total" = 1373,
"Comerciais leves" = 1374,
"Caminhões" = 1375,
"Ônibus" = 1376
),
first.date = "1993-01-01",
use.memoise = FALSE
)

Além disso fazemos o tratamento necessário para obter um objeto de classe tsibble, pois precisamos desse formato para a próxima etapa de modelagem e previsão:

anfavea <- raw_anfavea %>%
dplyr::select("date" = "ref.date", "variable" = "series.name", "value") %>%
dplyr::mutate(date = tsibble::yearmonth(.data$date)) %>%
tsibble::as_tsibble(key = "variable", index = "date")
anfavea

Uma rápida visualização dos dados sempre é importante:

anfavea %>%
fabletools::autoplot(value) +
ggplot2::facet_wrap(
~variable, 
scales = "free_y"
) +
ggplot2::labs(
title = "Produção de veículos desagregada - Brasil",
x = NULL,
y = "Unidades",
caption = "Dados: ANFAVEA | Elaboração: analisemacro.com.br"
) +
ggplot2::theme(legend.position = "none")

Para gerar previsões hierárquicas usaremos a família de pacotes do tidyverts (você não leu errado), que possibilita um fluxo de trabalho em apenas 5 passos:

1) Transforme os dados para um objeto tsibble contendo as séries desagregadas do nível inferior (em nosso exemplo todas exceto o "Total");

2) Utilize fabletools::aggregate_key() para definir a estrutura de agregação;

3) Especifique um modelo a ser estimado com fabletools::model() para cada série e suas desagregações;

4) Utilize fabletools::reconcile() para indicar uma abordagem (bottom-up, top-down, etc.) para gerar previsões desagregadas coerentes de acordo com o modelo;

5) Por fim, use a função fabletools::forecast() para gerar previsões para toda a estrutura de agregação.

Especificando a hierarquia da série:


prod_veiculos <- anfavea %>%
dplyr::filter(!variable == "Total") %>%
fabletools::aggregate_key(variable, value = sum(value, na.rm = TRUE))
prod_veiculos

Estimar modelos restringindo a amostra e apontar abordagens de previsão hierárquica:


fit <- prod_veiculos %>%
dplyr::filter(lubridate::year(.data$date) <= 2017) %>%
fabletools::model(baseline = fable::ETS(value)) %>%
fabletools::reconcile(
bottom_up = fabletools::bottom_up(baseline),
top_down = fabletools::top_down(baseline),
ols = fabletools::min_trace(baseline, method = "ols")
)
fit

Gerar previsões fora da amostra:


fcst <- fabletools::forecast(fit, h = "2 years")
fcst

Visualizar previsões geradas (produção agregada e desagregada):


fcst %>%
fabletools::autoplot(
dplyr::filter(
prod_veiculos,
dplyr::between(
lubridate::year(.data$date),
2015,
2019
)
),
level = NULL,
size = 1.1
) +
ggplot2::facet_wrap(
~variable,
scales = "free_y"
) +
ggplot2::labs(
title = "Previsão hierárquica da produção de veículos",
y = "Unidades",
x = NULL
)

Calcular métricas de acurácia:


fcst %>%
dplyr::filter(fabletools::is_aggregated(variable)) %>%
fabletools::accuracy(prod_veiculos) %>%
dplyr::arrange(RMSE)

O objeto fcst de classe fable contém as previsões baseline bem como as previsões coerentes de cada abordagem, para as três categorias de veículos desagregadas e para a produção total. Vale enfatizar que as previsões agregadas baseline serão diferentes das previsões agregadas pela abordagem bottom_up, por exemplo.

Dado a escala das séries em diferentes níveis de agregação serem bastante diferentes, devido à agregação, deve-se tomar cuidado ao avaliar as métricas de acurácia. Acima exibimos a acurácia para a série agregada (produção total) conforme cada abordagem/modelo.

Neste caso, agregar as previsões baseline usando a abordagem top-down resultou em previsões mais precisas em comparação com a abordagem bottom-up.

Por fim, vale destacar que o objetivo desse exercício não contempla nenhum aprofundamento ou preocupação com a especificação econométrica, ajuste ou acurácia do(s) modelo(s), focando apenas na implementação prática de previsões hierárquicas.

 

Referências

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

Athanasopoulos, G., Ahmed, R. A., & Hyndman, R. J. (2009). Hierarchical forecasts for Australian domestic tourism. International Journal of Forecasting, 25, 146–166.

Gross, C. W., & Sohl, J. E. (1990). Disaggregation methods to expedite product line forecasting. Journal of Forecasting, 9, 233–254.

Hyndman, R. J., Ahmed, R. A., Athanasopoulos, G., & Shang, H. L. (2011). Optimal combination forecasts for hierarchical time series. Computational Statistics and Data Analysis, 55(9), 2579–2589.

Panagiotelis, A., Athanasopoulos, G., Gamakumara, P., & Hyndman, R. J. (2021). Forecast reconciliation: A geometric view with new insights on bias correction. International Journal of Forecasting, 37(1), 343–359.

Wickramasuriya, S., Athanasopoulos, G., & Hyndman, R. (2019). Optimal forecast reconciliation for hierarchical and grouped time series through trace minimization. Journal of the American Statistical Association, 114(526), 804–819.


1 Outros exemplos comuns de séries temporais que podem ser desagregadas são: IPCA, IGP-M, Contas Nacionais, produção industrial, consumo de energia elétrica, etc.

 

Detectando anomalias com o pacote {anomalize}

By | Hackeando o R

No Hackeando o R de hoje, mostraremos como capturar anomalias de séries temporais de forma rápida e simples. A grosso modo, essas anomalias nas séries aparecem quando eventos não esperados "distorcem" os seus valores, portanto, quando se trabalha com uma análise dos dados, é importante saber quais são esses valores e quando ocorreram, para isso, o pacote {anomalize} nos ajuda nessa tarefa.

O pacote por padrão utiliza o método STL (caso queira se aprofundar no assunto veja esse post), retirando os componentes de tendência e sazonalidade e evidenciando as anomalias.

Iremos utilizar dados de preços e retornos de ações como exemplo, importando-os do ano de 2020 até o dia de hoje. Caso queira saber mais sobre, veja esse post.

 

library(tidyquant)
library(tidyverse)
library(timetk)
library(anomalize)
library(tibbletime)
# Define os ativos que irão ser coletados

tickers <- c("PETR4.SA", "ITUB4.SA", "ABEV3.SA", "JBSS3.SA")

# Define a data de início da coleta

start <- "2019-12-01"

# Realiza a coleta dos preços diários

prices <- getSymbols(tickers,
auto.assign = TRUE,
warnings = FALSE,
from = start,
src = "yahoo") %>%
map(~Cl(get(.))) %>%
reduce(merge) %>%
`colnames<-`(tickers)

# Calcula os retornos mensais

asset_returns <- Return.calculate(prices,
method = "log") %>%
na.omit() %>%
tk_tbl(preserve_index = TRUE,
rename_index = "date")


# Transforma os dados em long

asset_returns_long <- asset_returns %>%
pivot_longer(!date, names_to = "asset", values_to = "value")

Com nossos dados em mãos, podemos utilizar as funções dos pacote. A primeira, time_decompose(), nos fornece a decomposição da série, nos retornando as colunas dos nossos dados atuais observados (observed), os valores da sazonalidade (season), tendência (trend), e o "restante", que são os valores dos dados observados menos a sazonalidade e tendência.

A segunda função, anomalize(), nos fornece a detecção de anomalias, examinando a coluna "remainder".

Por fim, utilizamos a função time_recompose() para calcular os outliers com base nos valores dos dados observados.


# Cria o tibble com valores dos componentes e da anomalia

asset_anomalized <- asset_returns_long %>%
group_by(asset) %>%
time_decompose(value, merge = TRUE) %>%
anomalize(remainder) %>%
time_recompose()

Com os dados em mãos, podemos visualizar através da função plot_anomalies().


# Plota as anomalias dos retornos

asset_anomalized %>%
plot_anomalies(ncol = 4, alpha_dots = 0.25)+
ggplot2::labs(title = "Anomalias nos retornos de ações selecionadas",
caption = "Elaborado por analisemacro.com.br com dados do Yahoo Finance.")


O que nos chama a atenção nas anomalias do nossos dados são as datas de maiores ocorrências,  período do advento da pandemia de COVID-19 no Brasil.

Podemos também verificar essas anomalias nos gráficos de decomposição. Como exemplo, utilizamos o ativo PETR4.


# Transforma em tibble

petr4 <- prices %>%
tk_tbl(preserve_index = TRUE,
rename_index = "date") %>%
select(date, petr4 = `PETR4.SA`)

# Decompõe e calcula as anomalias

petr4_anomalized <- petr4 %>%
time_decompose(petr4) %>%
anomalize(remainder) %>%
time_recompose()

# Plota a decomposição com as anomalias

petr4_anomalized %>%
plot_anomaly_decomposition()+
ggplot2::labs(title = "Decomposição STL e anomalias do preço de fechamento da PETR4",
caption = "Elaborado por analisemacro.com.br com dados do Yahoo Finance.")


Vemos também as anormalidades em grande quantidade no mesmo período.

________________________

(*) Para entender mais sobre análise de séries temporais e mercado financeiro, confira nossos curso de Séries Temporais  e Econometria Financeira.
________________________

Criando uma dashboard de análise da inflação

By | Data Science

Quando o objetivo é analisar dados, é necessário utilizar as ferramentas adequadas para tornar os dados brutos em informação que seja útil. Para tal objetivo, uma dashboard pode ser o formato mais conveniente, dado seu poder de customização, compartilhamento e automatização. Nesse contexto, exploramos como exemplo a construção de uma dashboard simples aplicada à análise dos dados de inflação do Brasil, fazendo uso dos principais pacotes do R.

Visão geral

O objetivo geral é construir uma dashboard dinâmica onde seja possível analisar o comportamento histórico dos principais indicadores para acompanhamento de conjuntura do tema inflação, tais como: IPCA, IGP-M, INPC, etc. Além disso, para dar mais autonomia ao usuário final da dashboard, a mesma contará com opções de filtros de datas, indicadores, medidas, etc., tornando possível uma análise mais customizável.

Em resumo, a dashboard terá a seguinte aparência:

Você também pode conferir o resultado completo neste link.

Pacotes e framework

Para construir a dashboard você precisará dos seguintes pacotes disponíveis em sua instalação de R:


# Carregar pacotes
library(shiny)
library(ggplot2)
library(readr)
library(lubridate)
library(dplyr)
library(stringr)
library(forcats)
library(tidyr)
library(scales)
library(ggtext)
library(tsibble)
library(fabletools)
library(feasts)
library(Hmisc)
library(rmarkdown)
library(flexdashboard)

Optou-se por utilizar o framework dos pacotes shiny e flexdashboard, que oferecem uma sistemática de programação reativa e sintaxe simples e amigável, respectivamente, tornando o processo de criação de dashboards dinâmicas mais fácil. Além disso, a dashboard foi hospedada no serviço shinyapps.io e automatizada usando o GitHub Actions (confira neste link um tutorial de uso).

Para aprofundamento e detalhes confira o Curso de Análise de Conjuntura usando o R.

Criando a dashboard

O primeiro passo é criar um projeto do RStudio, para isso use usethis::create_project("nome_do_projeto").

Em seguida, criamos o arquivo principal da dashboard utilizando o template básico oferecido pelo pacote flexdashboard: basta navegar pelos menus File > New File > R Markdown > From Template > Flex Dashboard {flexdashboard} > OK e salvar o arquivo .Rmd na raiz do projeto.

No arquivo editamos os metadados com as definições desejadas para a dashboard, conforme abaixo:


---
title: "Diagnóstico da Inflação"
output:
flexdashboard::flex_dashboard:
orientation: rows
source_code: NULL
social: menu
navbar:
- { icon: "fa-github", href: "https://ENDEREÇO_DO_SITE/", align: right }
- { icon: "fa-linkedin", href: "https://ENDEREÇO_DO_SITE/", align: right }
- { icon: "fa-at", href: "mailto:MEU@EMAIL.COM", align: right }
runtime: shiny
---

Agora podemos começar a trabalhar nos dados e elementos visuais da dashboard. No primeiro chunk do documento (global) especificamos os pacotes, carregamos os dados e definimos objetos úteis a serem utilizados nos gráficos.

Os dados ficam salvos em uma pasta chamada "data" e são atualizados automaticamente por um script independente, visando diminuir dependências e tempo de carregamento da dashboard. Neste link você pode baixar os dados para poder reproduzir o exemplo.


# Carregar pacotes
library(shiny)
library(ggplot2)
library(readr)
library(lubridate)
library(dplyr)
library(stringr)
library(forcats)
library(tidyr)
library(scales)
library(ggtext)
library(tsibble)
library(fabletools)
library(feasts)
library(Hmisc)

# Carregar dados públicos previamente importados via pacotes
tbl_inflation <- readr::read_rds("data/tbl_inflation.rds")

# Objetos úteis na dashboard
colors <- c(
blue = "#282f6b",
red = "#b22200",
yellow = "#eace3f",
green = "#224f20",
purple = "#5f487c",
black = "black"
)

Em seguida, criamos uma linha usando cabeçalho Markdown de nível dois (------------------) e determinamos que esse elemento seja a sidebar da dashboard. Essa barra lateral é, usualmente, onde são exibidos os filtros e opções de interatividade, além de poder servir de espaço para textos informativos. No nosso exemplo, colocamos um texto breve e definimos, conforme chunk abaixo, os inputs que criamos através do shiny para aplicar filtros e manipulações de dados:


# Cria input do tipo "lista de caixas de seleção" com índices de preços como opções
# Objetivo: usuário pode escolher quaL indicador será exibido no gráfico
shiny::selectInput(
inputId = "variavel",
label = shiny::strong("Indicador:"),
choices = unique(tbl_inflation$variable),
selected = unique(tbl_inflation$variable)[1],
multiple = FALSE
)

# Cria input do tipo "calendário" de seleção de data de início e fim
# Objetivo: usar as datas selecionadas para filtrar amostra de dados utilizada no gráfico/cálculos
shiny::dateRangeInput(
inputId = "data",
label = shiny::strong("Data inicial e final:"),
min = min(tbl_inflation$date),
max = max(tbl_inflation$date),
start = min(tbl_inflation$date),
end = max(tbl_inflation$date),
language = "pt-BR",
separator = " - ",
format = "mm/yyyy"
)

# Cria input do tipo "campo numérico" para entrada de um ano para comparação
# Objetivo: comparar medidas (mediana e IQR) com dados observados referente ao ano
shiny::numericInput(
inputId = "ano",
label = shiny::strong("Comparar com o ano:"),
value = lubridate::year(max(tbl_inflation$date)),
min = lubridate::year(min(tbl_inflation$date)),
max = lubridate::year(max(tbl_inflation$date)),
step = 1
)

# Tratamento para atualizar o ano pré-selecionado no input$ano em resposta a uma
# mudança da amostra de dados definida pelo usuário no input$data:
# o objetivo é que quando o usuário diminui a amostra de dados, o ano de comparação
# selecionado não fique fora dessa nova amostra e seja atualizado para um novo
# valor o mais próximo possível dos valores extremos (anos) da nova amostra
shiny::observeEvent(
eventExpr = input$data, # observa mudanças do usuário na amostra de dados
handlerExpr = { # expressões que serão executadas quando input$data mudar

data_inicial <- lubridate::year(input$data[1])
data_final <- lubridate::year(input$data[2])

shiny::updateNumericInput( # atualiza o valor de input$ano quando a mudança é detectada
inputId = "ano",
value = if(!input$ano %in% data_inicial:data_final & data_inicial > input$ano){
data_inicial
} else
if(!input$ano %in% data_inicial:data_final & data_final < input$ano){
data_final
} else input$ano,
min = data_inicial,
max = data_final,
step = 1
)

}
)

# Cria input do tipo "lista de caixas de seleção" com componentes para filtragem
shiny::checkboxGroupInput(
inputId = "componentes",
label = shiny::strong("Componentes:"),
choices = c("% a.m.", "Tendência", "Sazonalidade", "Média"),
selected = c("% a.m.", "Tendência", "Média")
)

Uma vez definidos os inputs, passamos à construção dos outputs que serão dois gráficos neste caso. Para tal, criamos mais duas linhas: a primeira responsável por criar o gráfico dinâmico que compara a sazonalidade dos dados históricos com um determinado ano, especificado pelo usuário; e a segunda é responsável pelo gráfico dinâmico que mostra alguns componentes da série escolhida.

Veja, por exemplo, que o primeiro gráfico é afetado por mudanças no input referente ao filtro de datas, definição de ano de comparação e o indicador escolhido, sendo assim o script exige essas entradas/definições, utiliza esses valores armazenados para tratamento e cálculos nos dados, e, por fim, gera o gráfico de ggplot2 dinamicamente:


# Gerar gráfico dinâmico (se atualiza conforme o input da sidebar)
shiny::renderPlot({

# Use a função req para exigir que os valores do inputs sejam informados pelo usuário,
# isso evita que o R execute o script "ansiosamente"
shiny::req(
input$data,
input$ano %in% lubridate::year(input$data[1]):lubridate::year(input$data[2]),
input$variavel
)


# Valores dos inputs salvos em objetos auxiliar, por conveniência
data_inicial <- lubridate::floor_date(input$data[1])
data_final <- lubridate::floor_date(input$data[2])
data_compara <- input$ano
indicador <- input$variavel


# Script para calcular padrão sazonal mensal conforme inputs do usuário: mediana e IQR
seas_pattern <- tbl_inflation %>%
dplyr::group_by(
variable,
date_m = lubridate::month(.data$date, label = TRUE, locale = "pt_BR.utf8") %>%
stringr::str_to_sentence(locale = "br") %>%
forcats::as_factor()
) %>%
dplyr::filter(date >= data_inicial & date <= data_final) %>%
dplyr::summarise(
iqr = ggplot2::median_hilow(mom, conf.int = 0.5),
.groups = "drop"
) %>%
tidyr::unnest(cols = iqr) %>%
dplyr::rename("median" = "y", "date" = "date_m") %>%
dplyr::left_join(
tbl_inflation %>%
dplyr::filter(
date >= data_inicial & date <= data_final,
lubridate::year(.data$date) == data_compara
) %>%
dplyr::mutate(
date = lubridate::month(.data$date, label = TRUE, locale = "pt_BR.utf8") %>%
stringr::str_to_sentence(locale = "br") %>%
forcats::as_factor()
),
by = c("variable", "date")
) %>%
tidyr::pivot_longer(
cols = -c(variable, date, ymin, ymax),
names_to = "measure",
values_to = "value"
) %>%
dplyr::mutate(
measure = dplyr::recode(
measure,
"median" = "Mediana",
"mom" = as.character(data_compara)
)
) %>%
dplyr::filter(variable == indicador)


# Gerar gráfico dinâmico
seas_pattern %>%
ggplot2::ggplot() +
ggplot2::aes(x = date, y = value, color = measure, shape = measure, group = measure) +
ggplot2::geom_hline(yintercept = 0) +
ggplot2::geom_ribbon(
ggplot2::aes(
ymin = ymin,
ymax = ymax,
fill = "IQR (CI = 0,5)"
),
alpha = 0.2,
color = NA
) +
ggplot2::geom_line(size = 1.2) +
ggplot2::geom_point(size = 3) +
ggplot2::scale_color_manual(
NULL,
values = c(unname(colors["red"]), unname(colors["black"])),
guide = ggplot2::guide_legend(
override.aes = list(
shape = c(16, NA)
)
)
) +
ggplot2::scale_fill_manual(
NULL,
values = c("IQR (CI = 0,5)" = unname(colors["black"]))
) +
ggplot2::scale_shape_manual(
NULL,
values = c(16, NA)
) +
ggplot2::scale_y_continuous(
breaks = scales::extended_breaks(n = 6),
labels = scales::label_number(decimal.mark = ",", accuracy = 0.01),
minor_breaks = NULL
) +
ggplot2::labs(
title = paste0("**", indicador, "**: padrão sazonal"),
subtitle = paste0(
"% a.m., ",
paste0(
lubridate::year(data_inicial),
"m",
ifelse(
lubridate::month(data_inicial) < 10,
paste0("0", lubridate::month(data_inicial)),
lubridate::month(data_inicial)
),
"-",
lubridate::year(data_final),
"m",
ifelse(
lubridate::month(data_final) < 10,
paste0("0", lubridate::month(data_final)),
lubridate::month(data_final)
)
)
),
x = NULL,
y = NULL,
caption = "**Dados:** FGV e IBGE | **Elaboração:** Fernando da Silva"
) +
ggplot2::theme_light() +
ggplot2::theme(
legend.position = "bottom",
legend.key = ggplot2::element_blank(),
legend.key.width = ggplot2::unit(1, "cm"),
legend.key.height = ggplot2::unit(0.5, "cm"),
legend.text = ggplot2::element_text(size = 12),
plot.title = ggtext::element_markdown(size = 30, colour = colors["blue"]),
plot.subtitle = ggplot2::element_text(size = 16),
plot.caption = ggtext::element_markdown(size = 12),
axis.text = ggplot2::element_text(size = 12),
strip.background = ggplot2::element_blank(),
strip.text = ggplot2::element_text(size = 12, face = "bold", colour = colors["black"])
)

})

Após gerar os elementos visuais, utilize o botão Run Document no RStudio para visualizar o resultado, ou seja, a dashboard propriamente dita.

Os últimos passos envolvem fazer o deploy da dashboard e automatizar a coleta inicial de dados. Consulte as referências inicias para orientação sobre o assunto.

___________________

(*) Para aprofundamento e detalhes confira o Curso de Análise de Conjuntura usando o R.

Hackeando o R: 5 truques do Rmarkdown

By | Hackeando o R

Quando o assunto é criar documentos, estamos todos acostumados a realizar através de processadores de textos famosos como Word ou LibreOffice Writer. Para quem é da academia, talvez já tenha similaridade com outro tipo, tal como LaTex. Apesar disso, quando se entra no mundo do R, obviamente o trabalho fica muito mais fácil, e reportar os resultados utilizando esses processadores não se torna mais conveniente. Para tanto foi criado a ferramenta Rmarkdown, que facilita a produção de relatório no R. No Hackeando o R de hoje ensinaremos valiosos truques no mundo do Rmarkdown.

Para aprofundamento e detalhes confira o pacote de Cursos de Visualização de Dados no R.

Mostrar as imagens no console

Quando estamos criar um documento em Rmarkdown, estamos utilizando os códigos em chunks, que se definem por blocos de códigos que se completam quando realizamos o knit do documento. Utilizando os chunks, os resultados aparecem abaixo do próprio, dentro do script do R. Muitas vezes não é preferível que isso aconteça.

Para realizar a mudança, podemos seguir dois métodos. O primeiro pode ser mudando as configurações direto das configurações do Rstudio. Vá em Tools > Global Options > R markdown e desselecione a caixa "Show output inline for all R Markdown documents".

 

O segundo método consiste em colocar dentro do YAML o seguinte código: editor_options: chunk_output_type: console

 

Diminuir tamanho da fonte

Se a linha do seu código for muito grande, é provável que ele não caiba dentro do chunk no PDF, dessa forma, pode atrapalhar o relatório.

Um método para resolver este problema é configurando cada chunk com a opção size = "tiny".

 

Para facilitar o trabalho, é possível configurar globalmente no relatório essa opção definindo no começo do arquivo o seguinte código:

knitr::opts_chunk$set(size = "tiny")

 

Salvar imagens automaticamente

Muitas vezes cria-se relatórios Rmarkdown em PDF cheio de gráficos e tabelas, mas as vezes é possível se encontrar na situação de exportar essas imagens geradas pelo Rmarkdown individualmente para outros lugares. Para a felicidades de todos, o Rmarkdown possui uma configuração que cria uma pasta contendo todas as imagens geradas dentro de uma pasta.

A primeira forma pode ser mudando as configurações do YAML, utilizando o código keep_md: yes. Será salvo os arquivos de gráficos e tabelas individualmente.

 

Para caso queira que seja salvo em formato de imagem, como jpg ou png, pode-se utilizar dentro da configuração de cada chunk o código dev = "png". Para caso queira os dois formato, utiliza-se dev = c("png", "jpg").

Da mesma forma que a configuração do tamanho da fonte do chunk, é útil configurar para todo o relatório. É possível utilizando:


knitr::opts_chunk$set(dev = "png", # Salva como png
dpi = 300, # Configura a qualidade
echo = TRUE, # Mostra o código
cache = TRUE) # Cria o cache

 

Utilizando o Rstudio visual editor

Para quem está começando no Rmarkdown, ou não tem familiaridade com qualquer outro tipo de criador de documentos do tipo, e ainda possui uma dificuldade de escrever e imaginar o que será retornado no documento final, o Rstudio facilita disponibilizando o Visual Editor. Para acessá-lo, é necessário clicar no compasso no lado superior direito.

Pular páginas

É possível também pular páginas manualmente quando necessário no Rmarkdown. É viável de utilizar quando queira deixar o mais bem formatado as páginas possível. Esse comando é oriundo do LaTeX, mas o Rmarkdown reconhece o código. Para pular uma página deve-se utilizar

\newpage

fora do chunk.

Considerações

Elencamos apenas 5 dicas que podem ajudar quem está começando no mundo do Rmarkdown, mas que são valiosas. As possibilidades de configurações são enormes, sendo difícil colocar em apenas um post. Para quem deseja se aprofundar estaremos lançando nosso pacote de cursos de Visualização de dados no R, em que é oferecido o curso sobre Produção de Relatórios em Rmarkdown.

________________________

(*) Para aprofundamento e detalhes confira o pacote de Cursos de Visualização de Dados no R.

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":""}