Exibindo observações como imagens no ggplot2

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ê!

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

Compartilhe esse artigo

Facebook
Twitter
LinkedIn
WhatsApp
Telegram
Email
Print

Comente o que achou desse artigo

Outros artigos relacionados

Como tratar dados no Python? Parte 5: renomeando colunas

Como dar novos nomes significativos para as colunas em uma tabela de dados usando Python? Neste tutorial mostramos os métodos de renomeação de colunas disponíveis na biblioteca pandas, que tem como vantagem sua sintaxe simples e prática.

Como tratar dados no Python? Parte 4: operações por grupos

Como mensalizar dados diários? Ou como filtrar os valores máximos para diversas categorias em uma tabela de dados usando Python? Estas perguntas são respondidas com os métodos de operações por grupos. Neste tutorial mostramos estes métodos disponíveis na biblioteca pandas, que tem como vantagem sua sintaxe simples e prática.

Boletim AM

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

Boletim AM

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

como podemos ajudar?

Preencha os seus dados abaixo e fale conosco no WhatsApp

Boletim AM

Preencha o formulário abaixo para receber nossos boletins semanais diretamente em seu e-mail.