Introdução ao
{ggiraph}
Ícaro Bernardes | BIT::Analytics

VII SER International Seminar on Statistics with R
Maio de 2023

  • Bacharel em Eng. Química (UFBA)
  • Membro de grupo de pesquisa em estatística aplicada durante a graduação (GAMMA/UFBA)
  • Co-fundador da startup de análise de dados, BIT::Analytics

Membro ativo em comunidades de dataviz

ggplot

Compondo gráficos com camadas

O {ggplot2} tem como base o conceito de “Gramática de gráficos”. Isto é, os gráficos são compostos através da combinação entre elementos individuais.

ggplot

Compondo gráficos com camadas

Frequentemente encontramos em gráficos ao menos três tipos de elementos que nos permitem produzir uma representação visual das variáveis presentes em um banco de dados:

Formas geométricas

geom
Regras do mapeamento

scale
Estética e decoração

theme

ggplot

Compondo gráficos com camadas

ggplot(bancodedados) +
  geom_point(
    aes(x = year, y = score, color = score), size = 10
  ) +
  scale_color_gradientn(
    colours = rio.paletter("Mangueira")
  ) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )
Formas geométricas

geom

ggplot

Compondo gráficos com camadas

ggplot(bancodedados) +
  geom_point(
    aes(x = year, y = score, color = score), size = 10
  ) +
  scale_color_gradientn(
    colours = rio.paletter("Mangueira")
  ) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )
Regras do mapeamento

scale

ggplot

Compondo gráficos com camadas

ggplot(bancodedados) +
  geom_point(
    aes(x = year, y = score, color = score), size = 10
  ) +
  scale_color_gradientn(
    colours = rio.paletter("Mangueira")
  ) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )
Estética e decoração

theme

A função aes()

Mapeando variáveis

A função aes() é o elo de ligação entre as variáveis do banco de dados e as formas geométricas em um gráfico.

# A tibble: 19 × 3
    year score school                               
   <dbl> <dbl> <chr>                                
 1  2010  498. Beija-Flor de Nilópolis              
 2  2010  493. Imperatriz Leopoldinense             
 3  2010  496. Unidos de Vila Isabel                
 4  2011  499. Beija-Flor de Nilópolis              
 5  2010  493. Mocidade Independente de Padre Miguel
 6  2011  491. Imperatriz Leopoldinense             
 7  2010  496. Estação Primeira de Mangueira        
 8  2011  495. Acadêmicos do Salgueiro              
 9  2010  490. União da Ilha do Governador          
10  2011  494. Unidos de Vila Isabel                
11  2010  498. Acadêmicos do Grande Rio             
12  2010  483. Unidos do Viradouro                  
13  2010  496. Acadêmicos do Salgueiro              
14  2011  497. Unidos da Tijuca                     
15  2011  491. Mocidade Independente de Padre Miguel
16  2010  500. Unidos da Tijuca                     
17  2010  491. Portela                              
18  2011  484. São Clemente                         
19  2011  493. Estação Primeira de Mangueira        
aes(
  x = year,
  y = score,
  color = score
)

É incrível como o {ggplot} nos permite expressar variáveis em uma linguagem visual. Mas por que usar {ggiraph} para gerar gráficos interativos?

Por que ggiraph?

Interatividade num vapt-vupt

O {ggiraph} é uma extensão do {ggplot2} e do {htmlwidgets} que traduz elementos ggplot em suas contrapartes na biblioteca d3.js.

A proposta dos autores David Gohel e Panagiotis Skintzos é facilitar a criação de gráficos interativos/dinâmicos em documentos HTML feitos em Quarto/R Markdown e apps feitos em Shiny.

Por que ggiraph?

Interatividade num vapt-vupt

O {ggiraph} segue a mesma filosofia do {ggplot}, mas com elementos interativos.

geom_point()

ggplot
geom_point_interactive()

ggiraph

Por que ggiraph?

Interatividade num vapt-vupt

# Versão estática c/ elementos interativos e sintaxe ggplot
estatico <- ggplot(bancodedados) +
  ## Elemento interativo (geom)
  geom_point_interactive(
    aes(x = year, y = score, color = score), size = 10
  ) +
  ## Mapeamentos interativos
  aes(
    tooltip = school,
    data_id = school,
    onclick = 'this.style.r = "20";'
  ) +
  scale_color_gradientn(
    colours = rio.paletter("Mangueira")
  ) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )

# Versão interativa
ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")

Por que ggiraph?

Interatividade num vapt-vupt

Etapas de criação de um gráfico interativo ggiraph:

Uso de elementos interativos
geom, scale, etc
geom_point_interactive(
  aes(x = year, y = score, color = score),
  size = 10
) 
Uso de mapeamentos interativos
tooltip, data_id e onclick
aes(
  tooltip = school,
  data_id = school,
  onclick = 'this.style.r = "20";'
)
Criação do objeto interativo
girafe com ggobj e options
ggiraph::girafe(
  # É fundamental declarar o argumento *ggobj* na função
  ggobj = estatico, 
  bg = "#0c0c0c"
)

Argumentos aes() do ggiraph

Mapeando interatividade

Três novos argumentos fazem a mediação entre o banco de dados e a peça interativa no ggiraph:

Cria tooltips com HTML

tooltip
Agrupa formas geométricas

data_id
Comandos JS por clique

onclick

Argumentos aes() do ggiraph

Mapeando interatividade

estatico <- ggplot(bancodedados) +
  geom_point_interactive(
    aes(x = year, y = score, color = score), size = 10
  ) +
  aes(
    # Tooltip é uma string que aceita código HTML e CSS
    tooltip = glue::glue(
      "<img src='www/images/escudos/{filename}.jpg' width='150px;'>
      <div style='width:110px;text-align:center;padding:20px;'>{school}</div>"
    )
  ) +
  scale_color_gradientn(colours = rio.paletter("Mangueira")) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )

ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")
Cria tooltips com HTML

tooltip

Argumentos aes() do ggiraph

Mapeando interatividade

estatico <- ggplot(bancodedados) +
  geom_point_interactive(
    aes(x = year, y = score, color = score), size = 10
  ) +
  aes(
    # data_id é similar ao argumento group do aes()
    data_id = year
  ) +
  scale_color_gradientn(colours = rio.paletter("Mangueira")) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )

ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")
Agrupa formas geométricas

data_id

Argumentos aes() do ggiraph

Mapeando interatividade

estatico <- ggplot(bancodedados) +
  geom_point_interactive(
    aes(x = year, y = score, color = score), size = 10
  ) +
  aes(
    # onclick é uma string com comandos JS disparados ao clicar numa forma geométrica
    onclick = 'this.style.r = "20";
    this.style.fill = "red";
    setTimeout(() => {  this.style.r = "12"; }, 1000);'
  ) +
  scale_color_gradientn(colours = rio.paletter("Mangueira")) +
  scale_x_discrete() +
  theme_minimal() +
  theme(
    text = element_text(size = 30, color = "white"),
    axis.title = element_text(size = 40),
    plot.background = element_rect(fill = "#0c0c0c", color = "#0c0c0c")
  )

ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")
Comandos JS por clique

onclick

Customizando o gráfico

Família de funções opts_xxxx()

O argumento options é uma lista que recebe funções da família opts_xxxx()
ggiraph::girafe(
  ggobj = estatico,
  bg = "#0c0c0c",
  options = list(
    opts_tooltip(css = "width:100px;border-radius:50px 0;padding:20px;",
                 use_fill = TRUE),
    opts_hover(css = "r:20;"),
    opts_hover_inv(css = "opacity:0.1;"),
    opts_selection(
      css = girafe_css(
        css = "opacity:1;",
        text = "font-size:2em;",
        point = "stroke:gold;stroke-width:5px;"
      ),
      type = "multiple",
      only_shiny = FALSE
    )
  )
)

Hospedando o gráfico

Interatividade além do painel “Viewer”

Como o gráfico interativo gerado pela função girafe() é composto de elementos svg, ele pode ser inserido tanto em documentos HTML feitos em Quarto/R Markdown quanto em apps feitos em Shiny.

Hospedando o gráfico

Interatividade além do painel “Viewer”

# ```{r} Todo o processamento é realizado dentro de chunks

## Versão estática c/ elementos interativos e sintaxe ggplot
estatico <- ...

## Versão interativa
ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")

# ```

Em documentos HTML a função girafe() pode ser chamada diretamente dentro de um chunk R. A página HTML gerada pode ser então hospedada em quaiquer serviços. Duas opções gratuitas e fáceis de usar são o R Pubs e o Github Pages.

Hospedando o gráfico

Interatividade além do painel “Viewer”

# Todo o processamento é realizado no *server* dentro do ggiraph::renderGirafe()
output$interativo <- ggiraph::renderGirafe({
  
  ## Versão estática c/ elementos interativos e sintaxe ggplot
  estatico <- ...
  
  ## Versão interativa
  ggiraph::girafe(ggobj = estatico, bg = "#0c0c0c")
  
})

# A posição do gráfico é definida no *UI*
ggiraph::girafeOutput("interativo", width = "100%")

Já os Shiny apps, estes são divididos entre a parte do UI e do server. A função girafe() é chamada dentro da função renderGirafe() na parte do server. A posição do gráfico é definida através da função girafeOutput() na parte do UI.

Galeria de exemplos

Produções próprias com código comentado livre para acesso

Galeria de exemplos

Produções próprias com código comentado livre para acesso

Galeria de exemplos

Produções próprias com código comentado livre para acesso

Obrigado pela atenção!

O banco de dados usado nos exemplos pode ser obtido através do pacote {carnaval}

Vamos conversar mais sobre dados? @IcaroBSC @IcaroBernardes @icarobsc icaro@bitanalytics.dev.br