Data ScienceHackeando o R

Exibindo observações como imagens no ggplot2

By 10 de setembro de 2021 No Comments

Algumas vezes inserir imagens pode enriquecer um gráfico e atrair maior atenção. No R essa personalização da visualização de dados é relativamente simples usando o ggplot2 e suas extensões, conforme demonstramos nesse tutorial com exemplos inserindo imagens em pontos de observações.

Pacotes

Os pacotes utilizados neste exercício estão descritos a seguir. Você pode instalar os mesmos a partir do CRAN.


library(magrittr) # CRAN v2.0.1
library(purrr) # CRAN v0.3.4
library(glue) # CRAN v1.4.2
library(OECD) # CRAN v0.2.4
library(dplyr) # CRAN v1.0.7
library(lubridate) # CRAN v1.7.10
library(ggplot2) # CRAN v3.3.5
library(forcats) # CRAN v0.5.1
library(ggtext) # CRAN v0.1.1

Dados

Primeiro vamos coletar alguns dados e imagens de exemplo para construir uma visualização, objetivo é criar um gráfico da taxa de inflação de alguns países selecionados.

Os dados estão disponíveis na base da OECD e as imagens são provenientes do site flaticon.com e disponibilizados em nosso site. Importante: o script abaixo cria uma pasta temporária em seu computador e salva os arquivos de imagens (PNG) que utilizaremos neste exercício. Não execute o script se não deseja que isso seja feito.


# Link para imagens de bandeiras/país (Créditos: https://www.flaticon.com/)
url_imgs <- "https://analisemacro.com.br/wp-content/uploads/2021/09/"

# Nomes de arquivos PNG
country_names <- c(
"BRA",
"CHN",
"EU27_2020",
"IND",
"MEX",
"RUS",
"SAU",
"TUR",
"USA",
"ZAF"
)

# Criar pasta temporária
temp_folder <- tempdir()

# Baixar PNGs
purrr::walk2(
.x = url_imgs,
.y = country_names,
~download.file(
url = glue::glue("{.x}{.y}.png"),
destfile = glue::glue("{temp_folder}/{.y}.png"),
mode = "wb"
)
)

# Coletar e tratar dados de inflação para países selecionados
df_inflation <- OECD::get_dataset(
dataset = "MEI",
filter = "MEX+TUR+USA+BRA+CHN+IND+RUS+SAU+ZAF.CPALTT01.GY.M",
start_time = 2021
) %>%
dplyr::select(
"date" = `obsTime`,
"country" = `LOCATION`,
"value" = `obsValue`
) %>%
dplyr::mutate(
# Caminho do arquivo PNG
path_to_imgs = glue::glue("{temp_folder}/{country}.png"),
# Tag de imagem para ser usada no ggtext
country_imgs = glue::glue("<img src='{path_to_imgs}' width='30'/>"),
date = lubridate::ym(date),
fill_col = dplyr::if_else(country == "BRA", "#b22200", "#282f6b")
) %>%
dplyr::filter(date == lubridate::as_date("2021-07-01"))

df_inflation

## # A tibble: 10 x 6
## date country value path_to_imgs country_imgs fill_col
## <date> <chr> <dbl> <glue> <glue> <chr>
## 1 2021-07-01 MEX 5.81 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 2 2021-07-01 TUR 19.0 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 3 2021-07-01 USA 5.37 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 4 2021-07-01 BRA 8.99 "C:\\Users\\ferna\~ "<img src='C:\\User~ #b22200
## 5 2021-07-01 CHN 1 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 6 2021-07-01 IND 5.26 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 7 2021-07-01 RUS 6.47 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 8 2021-07-01 ZAF 4.65 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 9 2021-07-01 SAU 0.433 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b
## 10 2021-07-01 EU27_2020 2.5 "C:\\Users\\ferna\~ "<img src='C:\\User~ #282f6b

Criamos duas colunas importantes: a primeira (path_to_imgs) indica o caminho para o arquivo PNG salvo no computador e a segunda (country_imgs) é uma tag HTML para ser usada com o pacote ggtext, que interpreta o código lendo a imagem para ser renderizada no gráfico.

Um gráfico simples

Com os dados pronto podemos gerar uma simples visualização com o ggplot2, conforme abaixo:


# Gráfico simples
plot_inflation <- df_inflation %>%
ggplot2::ggplot(
ggplot2::aes(
x = forcats::fct_reorder(country, value, .desc = TRUE),
y = value,
fill = fill_col,
color = fill_col,
label = format(round(value, 2), nsmall = 2, decimal.mark = ","),
width = 0.6
)
) +
ggplot2::geom_col() +
ggplot2::geom_text(vjust = -0.5, fontface = "bold", size = 4.5) +
ggplot2::geom_hline(yintercept = 0, color = "black", size = 1) +
ggplot2::scale_color_identity(aesthetics = c("fill", "color")) +
ggplot2::scale_y_continuous(breaks = c(0, 5, 10, 15, 20), limits = c(0, 20)) +
ggplot2::theme_minimal() +
ggplot2::labs(
title = "**Inflação**",
subtitle = glue::glue("Países selecionados, {format(max(df_inflation$date), '%B/%Y')}"),
y = "% a/a",
x = NULL,
caption = "<br>**Dados:** OECD | **Gráfico:** analisemacro.com.br"
) +
ggplot2::theme(
panel.grid.minor = ggplot2::element_blank(),
plot.title = ggtext::element_markdown(size = 20),
plot.subtitle = ggplot2::element_text(size = 16),
plot.caption = ggtext::element_markdown(size = 12),
axis.text = ggplot2::element_text(size = 14, face = "bold"),
axis.title.y = ggplot2::element_text(size = 14, face = "bold")
)

plot_inflation

Gráfico com imagens: ggplot2 + ggtext

Vamos supor que queiramos enriquecer a visualização anterior inserindo imagens das bandeiras dos países no topo de cada coluna. Isso pode ser feito facilmente com o geom_richtext que, como o próprio nome diz, é muito útil para melhorar renderização e formatação de textos em gráficos do ggplot2.

Dessa forma, basta criar uma tag HTML img indicando a fonte do arquivo PNG e uma largura, conforme a coluna country_imgs do nosso objeto de dados, para incorporar uma imagem em vez de apenas formatar texto.


# Gráfico com imagens
plot_inflation +
ggtext::geom_richtext(
ggplot2::aes(x = country, y = value, label = country_imgs),
size = 1,
fill = NA,
label.color = NA
)

Também podemos inserir as imagens no eixo X com o código abaixo, e observe que estamos replicando praticamente o mesmo código, mas mudando a estética principal aes() para ter x = country_imgs e o elemento do theme para axis.text.x = ggtext::element_markdown().


# Gráfico com imagens no eixo
df_inflation %>%
ggplot2::ggplot(
ggplot2::aes(
x = forcats::fct_reorder(country_imgs, value, .desc = TRUE),
y = value,
fill = fill_col,
color = fill_col,
label = format(round(value, 2), nsmall = 2, decimal.mark = ","),
width = 0.6
)
) +
ggplot2::geom_col() +
ggplot2::geom_text(vjust = -0.5, fontface = "bold", size = 4.5) +
ggplot2::geom_hline(yintercept = 0, color = "black", size = 1) +
ggplot2::scale_color_identity(aesthetics = c("fill", "color")) +
ggplot2::scale_y_continuous(breaks = c(0, 5, 10, 15, 20), limits = c(0, 20)) +
ggplot2::theme_minimal() +
ggplot2::labs(
title = "**Inflação**",
subtitle = glue::glue("Países selecionados, {format(max(df_inflation$date), '%B/%Y')}"),
y = "% a/a",
x = NULL,
caption = "<br>**Dados:** OECD | **Gráfico:** analisemacro.com.br"
) +
ggplot2::theme(
panel.grid.minor = ggplot2::element_blank(),
plot.title = ggtext::element_markdown(size = 20),
plot.subtitle = ggplot2::element_text(size = 16),
plot.caption = ggtext::element_markdown(size = 12),
axis.text = ggplot2::element_text(size = 14, face = "bold"),
axis.text.x = ggtext::element_markdown(margin = ggplot2::margin(t = -5, unit = "pt")),
axis.title.y = ggplot2::element_text(size = 14, face = "bold")
)

Espero que esses exemplos tenham sido úteis para você!

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