---
title: "Visualização de dados"
subtitle: "Aula 3"
author: "Bruno Montezano"
institute: "Grupo Alliance Programa de Pós-Graduação em Psiquiatria e Ciências do Comportamento Universidade Federal do Rio Grande do Sul"
date: last-modified
date-format: long
lang: pt-br
execute:
echo: true
format:
revealjs:
incremental: true
smaller: true
theme: [default, ../assets/custom.scss]
logo: "../assets/logo_ufrgs.png"
bibliography: references.bib
code-annotations: select
---
## Conteúdo de hoje
- Pacote `ggplot2`
- Gramática dos gráficos
- Estética
- Mapeamento
- Gráficos básicos
- Personalização de gráficos
- Exemplos práticos
- Extensões de `ggplot2`
## Que a Força esteja com você!
::: columns
::: {.column width="70%"}
Para a aula de hoje, vamos usar os `dados_starwars`.
Este conjunto de dados contém 14 variáveis de 87 personagens dos filmes da saga Star Wars.
No decorrer da aula, vamos introduzir outras bases de dados para exemplificar
cada tipo de gráfico.
:::
::: {.column width="30%"}
![](../assets/star_wars_poster.jpg)
:::
:::
## `dados_starwars`
```{r carregar-starwars}
library(dados)
library(dplyr)
dados_starwars
```
## `ggplot2`
![](../assets/logo_ggplot2.png){fig-align="center" width="45%"}
## Exemplos iniciais de `ggplot2`
::: columns
::: {.column width="50%"}
```{r exemplo-inicial-ggplot2-codigo}
#| eval: false
library(ggplot2)
dados_starwars |>
ggplot() +
aes(x = massa, y = altura) +
geom_point(color = "forestgreen", size = 3) +
xlab("Massa (kg)") +
ylab("Altura (cm)") +
ggtitle("Altura e massa dos personagens") +
theme_bw(base_size = 18)
```
```{r exemplo-inicial-ggplot2-codigo-com-filter}
#| eval: false
dados_starwars |>
filter(!is.na(genero)) |>
ggplot() +
aes(x = massa, y = altura, color = genero) +
geom_point(size = 4, alpha = 0.7) +
xlab("Massa (kg)") +
ylab("Altura (cm)") +
ggtitle("Altura e massa dos personagens",
"Estratificado por gênero") +
theme_minimal(base_size = 20) +
scale_color_discrete(name = "Gênero")
```
:::
::: {.column width="50%"}
```{r exemplo-inicial-ggplot2-output}
#| echo: false
#| out-width: 100%
#| fig-align: "center"
library(ggplot2)
ggplot(data = dados_starwars,
aes(x = massa, y = altura)) +
geom_point(color = "forestgreen", size = 3) +
xlab("Massa (kg)") +
ylab("Altura (cm)") +
ggtitle("Altura e massa dos personagens") +
theme_bw(base_size = 18) #+
#theme(plot.background = element_rect(fill = "#f0f1eb"))
ggplot(data = dados_starwars |>
filter(!is.na(genero)),
aes(x = massa, y = altura, color = genero)) +
geom_point(size = 4, alpha = 0.7) +
xlab("Massa (kg)") +
ylab("Altura (cm)") +
ggtitle("Altura e massa dos personagens",
"Estratificado por gênero") +
theme_minimal(base_size = 20) +
scale_color_discrete(name = "Gênero")
#theme(plot.background = element_rect(fill = "#f0f1eb"))
```
:::
:::
## Gramática de gráficos em camadas
O pacote `ggplot2` segue duas filosofias que facilitam a compreensão do processo de construção de gráficos:
::: nonincremental
- Um gráfico estatístico é uma representação visual dos dados por meio de atributos estéticos (posição, cor, forma, tamanho) de formas geométricas (pontos, linhas, curvas) [@thegram2005]
- Um gráfico pode ser construído em camadas (sobreposição de elementos visuais) [@layered-grammar]
:::
## Camadas
::: {.panel-tabset}
## Canvas
```{r canvas}
#| out-width: 75%
#| fig-align: "center"
dados_starwars |>
ggplot()
```
## Eixos
```{r eixos}
#| out-width: 75%
#| fig-align: "center"
dados_starwars |>
ggplot() +
aes(x = massa, y = altura)
```
## Geometria
```{r geometria}
#| out-width: 75%
#| fig-align: "center"
dados_starwars |>
ggplot() +
aes(x = massa, y = altura) +
geom_point()
```
## Cor
```{r cor}
#| out-width: 75%
#| fig-align: "center"
dados_starwars |>
ggplot() +
aes(x = massa, y = altura, color = genero) +
geom_point()
```
## Forma
```{r forma}
#| out-width: 75%
#| fig-align: "center"
dados_starwars |>
ggplot() +
aes(x = massa, y = altura, shape = sexo_biologico) +
geom_point()
```
:::
## Por que o `+`?
O `ggplot2`, diferentemente dos outros pacotes do Tidyverse, não usa o *pipe*
(`|>`) porque o `ggplot2` surgiu [antes que o autor tomasse conhecimento do
pipe](https://www.reddit.com/r/dataisbeautiful/comments/3mp9r7/comment/cvi19ly/?utm_source=share&utm_medium=web2x&context=3).
. . .
![](../assets/hadley_sobre_pipe.png){fig-align="center"}
## Dica: Como escolher o gráfico mais adequado?
## Gráfico de pontos (dispersão)
Geralmente usado para visualizar a associação de duas variáveis contínuas.
. . .
Exemplo: verificar a associação entre altura e massa nos personagens
do Star Wars.
. . .
```{r scatterplot-altura-massa}
#| fig-align: "center"
#| out.width: "70%"
# O código abaixo gera a figura do slide
dados_starwars |> # <1>
filter(massa < 1000) |> # <2>
ggplot() + # <3>
aes(x = massa, y = altura) + # <4>
geom_point() # <5>
```
1. Usar os `dados_starwars`
2. Manter apenas observações com menos de 1.000kg de massa
3. Iniciar o canvas do `ggplot2`
4. Mapear massa no eixo `x` e altura no eixo `y`
4. Adicionar geometria de pontos com `geom_point()`
## `ggplot2` é extremamente versátil
## `dados_gapminder`
::: columns
::: {.column width="55%"}
Para aprender o próximo gráfico, vamos usar os `dados_gapminder`.
Trata-se de um projeto sueco criado por Hans Rosling que coleta
dados sobre diversas tendências globais. Na parte dos dados que vamos utilizar,
temos informações de 1952 a 2007 (intervalos de 5 anos).
Estes dados possuem 1.704 observações e 6 variáveis, sendo elas: `pais`,
`continente`, `ano`, `expectativa_de_vida`, `populacao`, `pib_per_capita`.
:::
::: {.column width="45%"}
![](../assets/logo_gapminder.png)
:::
:::
## Exibindo `dados_gapminder`
```{r printar-gapminder}
dados_gapminder
```
## Gráfico de linhas
Utilizamos o `geom_line()` para fazer gráficos de linhas. Eles são ótimos para
representar *séries temporais*, ou seja, observações medidas repetidamente em
intervalos de tempo.
. . .
Tal qual no gráfico de pontos, precisamos definir as posições $x$ e $y$ para
construirmos os gráficos de linhas.
. . .
No próximo slide, vamos olhar um exemplo de gráfico de linha do PIB per capita
do Brasil ao decorrer dos anos.
## PIB per capita do Brasil
::: {.panel-tabset}
## Linhas
```{r pib-do-brasil}
#| fig-align: "center"
#| out.width: "70%"
dados_gapminder |>
filter(pais == "Brasil") |>
ggplot() +
aes(x = ano, y = pib_per_capita) +
geom_line()
```
## Eixos
```{r pib-do-brasil-eixos}
#| fig-align: "center"
#| out.width: "65%"
dados_gapminder |>
filter(pais == "Brasil") |>
ggplot() +
aes(x = ano, y = pib_per_capita) +
geom_line() +
scale_x_continuous(breaks = seq(1952, 2007, 5)) +
scale_y_continuous(labels = scales::dollar_format(prefix = "R$ ",
decimal.mark = ",",
big.mark = "."))
```
## Tema e rótulos
```{r pib-do-brasil-tema-rotulos}
#| fig-align: "center"
#| out.width: "50%"
dados_gapminder |>
filter(pais == "Brasil") |>
ggplot() +
aes(x = ano, y = pib_per_capita) +
geom_line(linewidth = 2, color = "darkslateblue") +
scale_x_continuous(breaks = seq(1952, 2007, 5)) +
scale_y_continuous(labels = scales::dollar_format(prefix = "R$ ",
decimal.mark = ",",
big.mark = ".")) +
labs(x = "Ano", y = "PIB per capita",
title = "PIB per capita do Brasil ao passar dos anos",
subtitle = "De 1952 a 2007",
caption = "Fonte: Gapminder") +
theme_minimal(base_size = 16, base_family = "Charter")
```
:::
## Como os filmes da Pixar foram avaliados?
::: columns
::: {.column width="55%"}
Para o próximo gráfico, vamos tentar responder a seguinte pergunta:
"Segundo a CinemaScore, qual a nota mais recebida pelos filmes da Pixar?"
Para isso, vamos usar outra base de dados do pacote `dados`, chamada
`pixar_avalicao_publico`.
:::
::: {.column width="45%"}
![](../assets/logo_pixar.png)
:::
:::
## `pixar_avalicao_publico`
```{r mostrar-avaliacao-pixar}
pixar_avalicao_publico
```
. . .
```{r count-avaliacao-cinema-score}
pixar_avalicao_publico |>
count(nota_cinema_score) # A função count() serve para contar os valores únicos de uma variável
```
## Gráfico de barras
O gráfico de barras é muito usado para apresentar a frequência de uma
determinada categoria de uma variável.
. . .
No exemplo a seguir, acrescentamos o `ggplot2` ao código do slide anterior
para criar um gráfico de barras com a frequência de cada nota (A-, A, A+) dos
filmes da Pixar segundo o CinemaScore.
## Exemplo de gráfico de barras
```{r grafico-barras-cinema-score}
#| out-width: 60%
#| fig-align: "center"
# Este código gera o gráfico abaixo
pixar_avalicao_publico |> # <1>
count(nota_cinema_score) |> # <2>
ggplot() + # <3>
aes(x = nota_cinema_score, y = n) + # <4>
geom_col() # <5>
```
1. Usar a base `pixar_avalicao_publico`
2. Contar número de filmes em cada nota
3. Iniciar o canvas do `ggplot2`
4. Mapear os eixos `x` e `y`
5. Adicionar a geometria do gráfico de barras
## Gráfico de barras após ajustes
::: {.panel-tabset}
## Código
```{r grafico-barras-cinema-score-ajustado}
#| out-width: 60%
#| fig-align: "center"
#| eval: false
# O código abaixo gera o gráfico do painel ao lado
pixar_avalicao_publico |> # <1>
rename(nota = nota_cinema_score) |> # <2>
count(nota) |> # <3>
mutate( # <4>
nota = forcats::fct_na_value_to_level(nota, # <4>
"Sem escore"), # <4>
nota = factor(nota, # <5>
levels = c("A-", "A", # <5>
"A+", # <5>
"Sem escore")), # <5>
cor = dplyr::case_when(nota == "A" ~ "Colorido", # <6>
.default = "Cinza") # <6>
) |>
ggplot() + # <7>
aes(x = nota, y = n, fill = cor) + # <8>
geom_col(width = 0.5, show.legend = FALSE) + # <9>
scale_fill_manual(values = c("gray25", "darkorange")) + # <10>
labs(title = "A maioria dos filmes da Pixar (n = 13) receberam nota A.", # <11>
x = "Nota segundo CinemaScore", # <11>
y = "Número de filmes") + # <11>
theme_classic(base_size = 18, base_family = "Charter") # <12>
```
1. Pegar base da Pixar de avaliação do público
2. Renomear variável `nota_cinema_score`
3. Contar o número de filmes com cada nota
4. Transformar `NA` no valor "Sem escore"
5. Reordenar as notas da menor para a maior
6. Criar variável para colorir barra principal
7. Iniciar o canvas do `ggplot2`
8. Mapear variáveis do gráfico
9. Adicionar a geometria do gráfico de barras, retirar legenda e mudar largura das barras
10. Modificar as cores do preenchimento
11. Adicionar título e rótulos
12. Modificar tema, tamanho e família da fonte
## Gráfico
```{r grafico-barras-cinema-score-ajustado-output}
#| out-width: 100%
#| fig-align: "center"
#| echo: false
pixar_avalicao_publico |>
count(nota_cinema_score) |>
mutate(nota_cinema_score = forcats::fct_na_value_to_level(
nota_cinema_score, "Sem escore"),
nota_cinema_score = factor(nota_cinema_score,
levels = c("A-", "A",
"A+",
"Sem escore")),
cor = dplyr::case_when(
nota_cinema_score == "A" ~ "Colorido",
.default = "Cinza"
)) |>
ggplot() +
aes(x = nota_cinema_score, y = n, fill = cor) +
geom_col(width = 0.5, show.legend = FALSE) +
scale_fill_manual(values = c("gray25", "darkorange")) +
labs(title = "A maioria dos filmes da Pixar (n = 13) receberam nota A.",
x = "Nota segundo CinemaScore",
y = "Número de filmes") +
theme_classic(base_size = 18, base_family = "Charter")
```
:::
## Histograma
Histogramas são úteis para avaliarmos a distribuição de uma variável numérica.
. . .
Para criar histogramas, usamos o `geom_histogram()`. Para isso, precisamos
apenas do atributo $x$ (o eixo $y$ é construído de forma automática).
. . .
Na sequência, podemos observar um exemplo de histograma das notas dos filmes
da Pixar no Rotten Tomatoes.
. . .
```{r histograma-simples-rotten-tomatoes}
#| fig-align: "center"
#| out.width: "55%"
pixar_avalicao_publico |>
ggplot() +
aes(x = nota_rotten_tomatoes) +
geom_histogram()
```
## Exemplo de histograma "mais bonito"
```{r histograma-rotten-tomatoes}
#| fig-align: "center"
#| out.width: "100%"
pixar_avalicao_publico |>
ggplot() +
aes(x = nota_rotten_tomatoes) +
geom_histogram(fill = "cyan4") +
labs(x = "Nota segundo críticos do Rotten Tomatoes",
y = "Contagem",
title = "Como se distribuem as notas segundo os críticos do Rotten Tomatoes?",
subtitle = "Dados de 24 filmes da Pixar",
caption = "Fonte: Wikipedia") +
theme_light(base_size = 16, base_family = "Charter")
```
## Box plot
Os box plots são úteis para estudar a distribuição de uma variável,
especialmente ao comparar várias distribuições.
. . .
Para construir um box plot, usamos o `geom_boxplot()`. Para tal, usamos
atributos $x$ e $y$, mapeando uma variável categórica para o atributo $x$.
. . .
```{r boxplot-gapminder}
#| fig-align: "center"
#| out.width: "60%"
dados_gapminder |>
filter(ano == 1952) |>
ggplot() +
aes(x = continente, y = expectativa_de_vida) +
geom_boxplot()
```
## Box plot após ajustes
```{r boxplot-apos-ajustes}
#| fig-align: "center"
dados_gapminder |>
filter(ano == 1952) |>
ggplot() +
aes(x = continente, y = expectativa_de_vida, color = continente) +
geom_boxplot(show.legend = FALSE) +
theme_classic(base_size = 16, base_family = "Charter") +
labs(x = "Continente", y = "Expectativa de vida (em anos)",
title = "Como se distribuía a expectativa de vida em cada continente em 1952?",
caption = "Fonte: Gapminder") +
annotate("text", x = 1, y = 65,
label = "Em 1952,\na África tinha\numa expectativa\nde vida\nde 38,8 anos.",
size = 5,
family = "Charter")
```
## Títulos, labels e escalas
Para colocar títulos ou trocar os labels (rótulos) dos atributos, utilizamos
a função `labs()`.
. . .
Para mudar as escalas (textos e quebras), usamos as funções da família
`scale_[estética]_[opção]()`.
. . .
Para definir qual porção do gráfico deve ser mostrada (limites), podemos usar
as funções `xlim()` e `ylim()`.
## Cores
Para escolher manualmente as cores que coloriram ou preencheram um plot,
use as funções `scale_color_manual()` ou `scale_fill_manual()`.
. . .
Para trocar o nome das legendas geradas por atributos de cor,
use as funções `scale_color_discrete()` ou `scale_fill_discrete()`.
## Temas
Como vocês devem ter percebido, o `ggplot2` traz consigo alguns temas prontos
a partir de funções da família `theme_[estilo_do_tema]`.
. . .
Você também pode criar o seu próprio tema usando a função `theme()`.
Não teremos
como ver durante as aulas, pois requer um pouco mais de conhecimento
técnico, mas é um processo divertido de aprender!
## Dica: Extensões do `ggplot2`
* O `ggplot2` é muito potente, mas não possui todos os gráficos possíveis
* Por conta disso, a comunidade desenvolve extensões que vão desde pacotes
com novos temas ou cores, geometrias, eixos ou até a
[possibilidade de criar calendários customizados](https://r-coder.com/calendar-plot-r/) 😂
* A equipe do Tidyverse mantém uma [lista curada de extensões do `ggplot2`](https://exts.ggplot2.tidyverse.org/gallery/)
. . .
```{r calendario-mes-abril}
#| echo: false
#| fig-align: "center"
#| out.width: "60%"
calendR::calendR(year = 2023, month = 04,
special.days = c(17, 24),
special.col = "#bfe2f2",
low.col = "white",
title = "Aulas de R no mês de abril de 2023",
subtitle = "Exclusivas para o grupo de pesquisa Alliance",
weeknames = c("Segunda", "Terça",
"Quarta", "Quinta", "Sexta", "Sábado", "Domingo"),
lunar = FALSE)
```
## Tarefa de casa
* A partir dos dados `pinguins` do pacote `dados`, crie:
- Um gráfico de pontos (dispersão)
- Um box plot (variável numérica estratificada por uma variável categórica)
- Um histograma
* Escolha um dos seus gráficos para ajustá-lo e deixá-lo visualmente mais
agradável!
- Ajustar rótulos, tamanho da fonte, cores, adicionar título, e o que
mais você achar importante
- Lembre-se da função `labs()` e família `theme_[estilo_do_tema]()`
## Dica de leitura sobre visualização
::: columns
::: {.column width="50%"}
* [Data Visualization: A Practical Introduction](https://socviz.co/)
- Como criar visualizações efetivas
- Quais visualizações funcionam e quais não
- Como criar vários tipos de gráficos em `ggplot2`
- Como refinar os gráficos para apresentação
:::
::: {.column width="50%"}
![](../assets/capa_data_visualization.jpg){fig-align="center" width=90%}
:::
:::
## Referências
::: {#refs}
:::