Chapter 5 Módulo V

5.1 Gráficos com ggplot2

Nesta seção veremos como fazer gráficos sofisticados no R. Serão apenas noções básicas, uma vez que a ggplot2 propicia um controle total de quase todos os aspectos de um gráfico ao usuário. No entanto, já serão ferramentas sufcientes para confecionar e personalizar diversos gráficos no R. A quantidade de tipos de gráficos que podemos fazer com ggplot2 é imensurável. A ideia é enterdermos os conceitos básicos e estruturais do pacote para depois caminharmos com nossas próprias pernas.

5.2 Introdução

O pacote ggplot2 cria gráficos utilizando camadas de atributos, utilizando a chamada gramática de gráficos. Esta gramática permite construir gráficos componente por componente ao invés de termos que editar gráficos “pré-fabricados” como ocorre no base R e em todas as outras bibliotecas de linguagens usadas para Data Science, como matplotlib e seaborn de Python, por exemplo.

Nós não precisamos conhecer a gramática para começar a produzir gráficos com ggplot2. Todavia, ao compreendermos a estrutura da gramática de gráficos, podemos:

  • construir gráficos a partir de conceitos (do que desejamos fazer) ao invés de termos que lembrar comandos e opções;

  • conceber novos e melhorados gráficos.

O ggplot2, embora tenha surgido antes do tidyverse, também é um dos pacotes que do core deste meta-packge. Ele foi escrito por Hadley Wickham, o qual publicou o livro intitulado “ggplot2 Elegant Graphics for Data Analysis”. O sucesso de ggplot2 é tão expressivo que foram feitos APIs (Application Programming Interface) para que as funcionalidades do pacote pudessem ser empregadas em outra s linguagens, como Python por exemplo.

5.3 A gramática de gráficos

A gramática de gráficos foi um conceito desenvolvido por Leland Wilkinson em 1999 e publicado por ele em The Grammar of Graphics em 2005. Essa gramática define regras para estruturar elementos matemáticos e estéticos (aesthetics) em um gráfico propriamente dito. ggplot2 é escrito sob as regras desta gramática.

5.3.1 Estrutura da gramática de gráficos no ggplot2:

  • data
    • dados que contém as variáveis a serem plotadas ;
    • variáveis a serem retratadas no gráfico;
    • variáveis a serem mapeadas para os aesthetics (elementos perceptíveis) do gráfico;
  • Geoms (formas geométricas)
    • objetos e formas do gráfico (barras, pontos, linhas, etc)
  • Stats
    • transformações estatísticas , geralmente para sumarizar dados (média, variância, mediana, etc)
  • Scales
    • define quais elementos estéticos (aesthetics) do gráfico serão mapeados para as variáveis (ex: que cores serão mapeadas a quais valores)
  • Coordinate Systems
    • define como os dados serão mapeados para o plano/área do gráfico (Cartesiano, Polar, etc)
  • Facetting
    • divide os dados em subconjuntos para criar multiplas variações do mesmo gráfico (ex: gráficos em painel)

Todos esses elementos são tratados como layers e podem ser adiconadas a parte principal do gráfico utilizando-se o sinal +.

Neste curso, veremos de forma mais detalhada os elementos data, aesthetics, stats e facetting e o que significa cada um desses elementos na estrutura da gramática de gráficos.

Uma forma geral (template) para entender-se a estrutura do ggplot2, segundo o próprio Hadley Wickhan, no livro R for Data Science, é a seguinte:

ggplot(data = <DATA>) + 
  <GEOM_FUNCTION>(
     mapping = aes(<MAPPINGS>),
     stat = <STAT>, 
     position = <POSITION>,
     data = <DATA> # pode receber os dados diretamente
  ) +
  <SCALE_FUNCTION> + # uma para cada elemento estético
  <COORDINATE_FUNCTION> +
  <FACET_FUNCTION> # dividir o gráfico em subplots

É importante salientar que apesar dos dados estarem na função ggplot() (<DATA>), eles também podem ser incluídos diretamente em cada objeto geométrico. Quando for necessário criar-se uma nova camada a partir de dados diferentes daqueles que estão inicialmente nos gráficos está propriedade se mostrará muito útil.

A ideia é que todo gráfico pode ser representado por essa forma. Porém na criação de um gráfico, não é obrigatório especificar-se todas as partes acima. O ggplot2 já oferece um padrão para o sistema de coordenadas, para o stat, position e facet (subplot) só será utilizado quando necessário.

Para, exemplificar vamos utilizar os datasets utilizados no Módulo IV, carregue a tabelas originais com seus devidos comandos já mencionados.

5.4 Data (Dados)

Os dados utilizados com as funções de ggplot2 DEVEM ser armazenados como um tibble ou dataframe. Há possibilidade, inclusive, de se usar mais de um dataframe em um gráfico. A recomendação é que se defina e se certifique acerca dos tipos das variáveis antes de começar a construir um gráfico

5.5 A função ggplot()

Os dados que serão usados para plotagem serão especificados dentro da função ggplot(). Note que é ggplot() e não ggplot2(). O nosso dataframe/tibble sempre será primeiro argumento desta função.

Um outro argumento a ser passado para a função ggplot() são os aesthetics, utilizando a função auxiliar aes() que mapeia as variáveis dos dados para os elementos gráficos perceptíveis (estéticos), como a posição nos eixos dos gráficos, a definição de cores por categorias, etc.

Qualquer função subsequente vai herdar os dados e os aesthetics de ggplot(), a não ser que estes parâmetros sejam sobrescritos em outra camada. Para encadear outras funções a função ggplot(), usamos sempre +.

5.6 Aesthetics (elementos estéticos dos gráficos)

Variáveis são mapeadas para os aesthetics, o que significa que são traduzidas para os elementos estéticos do gráfico. A função aes() é quem faz esse mapeamento. Ela também pode ser especificada dentro de outras camadas que compões o gráfico, como geoms e stats, por exemplo . Os aesthetics mais utilizados são:

  • x - posição no eixo x;

  • y - posição no eixo y;

  • color ou colour - “cor de fora” ou do contorno do objeto;

  • fill - “cor de dentro” do objeto;

  • alpha - nível transparência do gráfico;

  • shape - forma dos marcadores (pontos, triângilos, cruz, etc);

  • size - tamanho (do raio) dos objetos.

5.7 Exemplos para aesthetics

Para fazermos um gráfico, primeiro precisamos indicar os dados e fazer o mapeamento das variáveis aos aesthetics. Isso reserva uma área de gráfico a ser utilizada.

library(ggplot2)

ggplot(data=tb_game_sales, mapping = aes(x = Genre , y=NA_Sales))

Vejamos um primeiro exemplo para o cruzamento entre Genre vs NA_Sales.

tb_game_sales %>%
  ggplot(mapping = aes(x=Genre, y=NA_Sales))+
  geom_point()

Note que não houve a necessidade de re-especificar os argumentos data e aes() para a função geom_point().

Poderíamos melhorar nosso gráfico adicionando cores dentro de aes(). Isso acrescentaria mais informação.

tb_game_sales %>%
  ggplot(mapping = aes(x=Genre, y=NA_Sales))+
  geom_point(aes(color=Platform))

Uma melhor forma de demonstrar os diferentes tipos de destino seria utilizar diferentes formas (argumento shape):

tb_game_sales %>%
  filter(Platform %in% c("Wii", "X360","PS3","PS4","N64")) %>% 
  ggplot(mapping = aes(x=Genre, y=NA_Sales, shape=Platform))+
  geom_point()

5.7.1 Mapping vs Setting aesthetics

Nos exemplos anteriores, poderíamos optar por usar apenas uma única cor ou um único shape que não fosse o padrão de “bolinha” na cor preta. O que deveríamos fazer então, ao invés de mapear variáveis para aesthetic, é setar a aesthetic contante.

Quando vamos mapear um aesthetic, as variáveis são passadas dentro de aes(); ao passo que quando vamos setar um aesthetic como constante, o valor é passado fora de aes().

Vejamos os exemplos anteriores com um aesthetic constante para cor e shape:

tb_game_sales %>% 
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4")) %>% 
  ggplot(mapping = aes(x=Genre, y=NA_Sales))+
  geom_point(color = "red")

tb_game_sales %>% 
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4")) %>% 
  ggplot(mapping = aes(x=Genre, y=NA_Sales))+
  geom_point(shape = 2)

Note que devemos passar as constantes para geom_point() (fora de aes()) - o elemento de objetos geométricos - e não para ggplot().

Veja quantos shapes podemos usar no R:

5.7.2 Geoms

Geoms são as formas geométricas a serem plotadas nos gráficos, exemplo geom_line(), geom_col(), geom_point(), etc. Eles diferem de um para o outro nos tipos de aesthetics que eles requerem ou entendem. Por exemplo: geom_point() requer aes(x, y), ao passo que geom_bar() requer aes(x) apenas.

Para obter ajuda digite ?geom_x.

5.7.3 Exemplos para Geoms

geoms para uma variável numérica (contínua de preferência)

p <- tb_game_sales %>% 
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4")) %>% 
  ggplot(mapping = aes(x=NA_Sales))

DICA: Note que podemos atribuir o resultado do gráfico a um objeto no R e acrescentar outras layers posteriormente.

p + geom_density()

p + geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

geoms para uma variável numérica discreta

# contagem
tb_game_sales %>% 
  mutate(Year = as.integer(Year)) %>% 
  filter(Platform %in% c("PS3", "PS4")) %>% 
  ggplot(mapping = aes(x = Year)) +
  geom_bar()
## Warning in mask$eval_all_mutate(quo): NAs introduzidos por coerção
## Warning: Removed 25 rows containing non-finite values (stat_count).

geoms para duas variáveis (contínuas)

geom_point() tambpem pode ser usado neste caso:

p <- tb_game_sales %>% 
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4")) %>% 
  ggplot(mapping = aes(x=Global_Sales, y=NA_Sales))

p + geom_point()

geoms para duas variáveis (uma discreta e uma contínua)

p <- tb_game_sales %>% 
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4"), Genre %in% c("Action","Racing","Shooter","Role-Playing","Sports"  )) %>% 
  ggplot(mapping = aes(x=Genre, y=NA_Sales))

p + geom_boxplot()

p + geom_violin()

geoms para gráficos de linha

tb_game_sales %>% 
  group_by(Year) %>% 
  summarise(media_global = mean(Global_Sales)) %>% ungroup() %>% 
  ggplot(mapping = aes(x=Year, y=media_global, group = 1))+
    geom_line()

No caso de gráficos de linhas, ao invés usar cores diferentes, poderíamos ainda alterar o tipo de linha conforme as categorias de uma 3ª variável, por meio do argumento linetype:

tb_game_sales %>%
  filter(Platform %in% c("PS", "PS2", "PS3", "PS4")) %>% 
  group_by(Year, Platform) %>% 
  summarise(media_global = mean(Global_Sales)) %>% 
  ggplot(mapping = aes(x=Year, y=media_global, linetype = Platform, group = Platform))+
    geom_line()

DICA: Há também outros geoms que você encontrará na página de ajuda.

5.7.4 Positions

Um aspecto dos gráficos de ggplot2 que não chega a ser uma layer, mas que será importante de observarmos diz respeito a ajustes de posição. Elas serão muito importantes para gráficos de de barras com duas variáveis.

Os ajustes de posição definirão como os geoms se localizam no gráfico, de modo que não ocupem o mesmo espaço. No exemplo do gráfico de barras, podemos fazer gráficos de barras justapostas ou empilhadas.

-position="stacked é o ajuste padrão de geom_point(). Ela coloca cada objeto na posição exata do contexto do gráfico. No caso de gráficos de barras, teríamos barras acumuladas (stacked):

tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="stack")

DICA: position = “dodge” coloca objetos sobrepostos um ao lado de outro. Nesse caso, teremos barras justapostas:

p_dodge <- tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge")

DICA: Se voce quiser inverter as coordenadas do gráfico, pode fazer isso trocando os parâmetros x e y e em aes(), ou utilizando a função coord_flip():

p_dodge + coord_flip()

  • position=“fill” também empilhará os elementos, mas irá normalizar a altura de todas as barras para que fiquem na mesma escala. Isso torna mais fácil comparar as proporções entre os grupos:
tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="fill")

  • position=“jitter” é útil para gráficos de dispersão, pois há um problema muito comum neste tipo de gráfico que é a sobreposição de pontos (overplotting). Com jitter, ggplot2 adiciona um ruído aleatório nas posições de X e Y para que eles não se sobreponham:
mpg %>%
  ggplot(mapping=aes(x=displ, y=hwy))+
           geom_point(position="jitter")

Há outros ajustes de posição bem úteis, como:

  • position=“nudge” afasta os rótulos dos pontos;
  • position=“identity” sobrepõe os elementos uns sobre os outros.

5.8 Facetting

As facetts em ggplot2 nos permitem criar vários gráficos com base em subconjuntos de dados e plotá-los numma mesma área. É uma técnica muito útil (quando temos variáveis categóricas) e desejamos visualizar o comportamento de diferentes categorias num mesmo gráfico.

Há duas funções que permitem criar facetas: facet_wrap() e facet_grid().

Tanto facet_wrap quanto facet_grid permitem a divisão do plot da(s) variável(is) passadas em aes() de acordo com as categorias de uma 3ª ou 3ª e 4ª variáveis.

tb_game_sales %>% 
  filter(Year > 2010) %>% 
  group_by(Year, Platform) %>% 
  summarise(media_global = mean(Global_Sales)) %>%
  ggplot(mapping = aes(x=Year, y=media_global, group = 1))+
    geom_line() +
  facet_wrap(~ Platform)
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

Note acima que podemos definir o número de linhas desejado para plotagem com o argumento nrow ou o número de colunas com ncol e automaticamente o outro argumento será determinado. O símbolo ~ é muito utilizado no R. Nesse casos significa as variáveis de aes() serão plotadas em função das variáveis Platform

No caso de facet_grid(), a organização do output será um pouco diferente. Será feito, como o próprio nome da função diz, um grid. Onde as linhas dirão respetio a uma das variáveis e a coluna à outra variável. É como se fosse um jogo de batalha naval, é uma matriz de pequenos gráficos. No caso anterior, com facte_wrap() isso não ocorre.

tb_game_sales %>% 
  filter(Year > 2010) %>% 
  group_by(Year, Platform) %>% 
  summarise(media_global = mean(Global_Sales)) %>%
  ggplot(mapping = aes(x=Year, y=media_global, group = 1))+
    geom_line() +
  facet_grid( ~ Platform)
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?
## geom_path: Each group consists of only one observation. Do you need to adjust the group aesthetic?

5.9 Títulos, rótulos, temas e legendas

Há duas formas de alterar títulos e rótulos dos eixos em ggplot2. Você pode optar por ggtitle("título do gráfico"), xlab("rótulo eixo x"), ylab("rótulo eixo y"). Ou então, pode usar labs(). No caso, de usar labs, você pode alterar todos esses campos e outros, como o de legenda dentro da mesma função.

Note, no entanto, que o parâmetro que controla o título da legenda muda dependendo do parâmetro dentro de mapping = aes() a partir do qual a legenda foi gerada. Normalmente, a legenda é gerada ou pelos parâmetros colour, fill, size, shape, linetype e alpha. Esses mesmos parâmetros, dependendo do caso, deverão ser passados dentro da função labs() para controlar o título da legenda, como por exemplo: labs(..., shape = "Título da legenda").

 tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge") +
  labs(title="Título do gráfico",
       x = "Rótulo eixo x",
       y = "Rótulo eixo y",
       colour = "Título da Legenda")

Há ainda funções específicas que também controlam o nome da legenda dependendo do argumento utilizado para gerar a legenda dentro de aes() e também a partir de qual tipo de dados, se contínuos ou discretos. Temos os seguintes casos:

  • scale_GERADOR_discrete(name="título da legenda")

  • scale_GERADOR_continuous(name="título da legenda")

Dessa forma, temos: scale_fill_discrete(name="título da legenda"), scale_fill_continuous(name="título da legenda"), scale_colour_discrete(name="título da legenda"), scale_colour_continuous(name="título da legenda"), e assim por diante para os demais argumentos geradores da legenda, como size, linetype, alpha e shape.

Podemos inclusive ter mais de um argumento de mapping dentro de aes() e podemos controlar as legendas de cada um, adicionando mais uma camada ao gráfico:

 tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge") +
  ggtitle("Volume de Vendas Globais \npor genero para PS3, PS4")+
  xlab("Plataforma")+
  ylab("Sales Value")+
  scale_fill_discrete(name="Genero")

5.10 Alterar cores e paleta de cores

Você deve ter notado, que na maioria dos gráficos, o ggplot2 utiliza cores padrão da biblioteca para as plotagens. Se você não estiver contente com a paleta de cores padrão utilizada pelo pacote no mapping de suas variáveis, você pode definir manualmente esses cores utilizando uma outra paleta ou outras cores de sua preferência.

O modo de alterar a paleta de cores utilizadas em um argumento de mapping dentro de aes() é por meio de funções do tipo scale_GERADOR_manual(), alterando-se o parâmetro values.

 tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge") +
  ggtitle("Volume de Vendas Globais \npor genero para PS3, PS4")+
  xlab("Plataforma")+
  ylab("Sales Value")+
  scale_fill_manual(name="Genero", values=c("blue", "yellow"))

Por meio dessas mesmas funções do tipo de funções do tipo scale_GERADOR_manual(), podemos alterar também os rótulos das categorias exibidas na legenda utilizando o argumento labels.

 tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge") +
  ggtitle("Volume de Vendas Globais \npor genero para PS3, PS4")+
  xlab("Plataforma")+
  ylab("Sales Value")+
  scale_fill_manual(name="Genero", values=c("red", "blue"),
                      labels=c("Ação", "Corrida"))

5.11 Área de Plotagem e Tema

Como já afirmamos antes, com ggplot2 é possível modificar praticamente todos os parâmetros do seu gráfico. E normalmente há mais de uma forma para se fazer cada uma das alterações. Com a função theme(), é possível controlar desde o tamanho dos elementos do de plotagem do gráfico, passando pelo tamnho do texto dos rótulos e indo até o tamanho dos quadrados ou “bolinhas” da legenda. No entanto, esta será uma pesquisa a ser feita por você.

Nesta seção traremos apenas algumas funções do ggplot2 que trazem alguns temas pré-formatados:

  • theme_gray(): plano de fundo cinza e linhas de grid brancas. É como se trouxesse os dados para frente para facilitar comparações;

  • theme_bw(): plano de fundo branco e linhas de grid cinzas. Recomendado para apresentações utilizando projetor;

  • theme_linedraw(): plano de fundo branco e linhas de grid com largura diferenciada.

  • theme_light(): linhas de grid cor cinza claro e com presença de eixos. Parecido como theme_linedraw();

  • theme_dark(): igual ao theme_light() mas com plano de fundo escuro. Faz linhas coloridas finas se destacarem;

  • theme_minimal(): tema minimalista sem plano de fundo;

  • theme_classic(): tema clássico sem linhas de grid;

  • theme_void(): tema vazio, sem cores de fundo e grid. Recomendado para plots de coordenadas não-usuais ou para desenhos.

 tb_game_sales %>% 
  filter(Platform %in% c("PS3", "PS4"), 
         Genre %in% c("Action","Racing")) %>% 
  ggplot(mapping = aes(x = Platform, y = Global_Sales, fill = Genre)) +
  geom_bar(stat = "identity", position="dodge") +
  ggtitle("Volume de Vendas Globais \npor genero para PS3, PS4")+
  xlab("Plataforma")+
  ylab("Sales Value")+
  scale_fill_manual(name="Genero", values=c("red", "blue"),
                      labels=c("Ação", "Corrida"))+
  theme_bw()

DICA: O ggplot2 alinha o título do gráfico sempre à esquerda. Você pode centralizar o título usando justamente a função theme(), que comentamos mais acima, escrevendo theme(plot.title = element_text(hjust=0.5). 0.5 indica que o título deve ficar no meio do gráfico, conforme alinhamento horizontal especificado (parâmetro hjust). element_text() é uma helper function que serve para controlar aspectos textuais como tamanho (size) e outros parâmetros como o próprio alinhamento horizontal.


5.12 Referências da seção

5.13 Exercícios

  1. Escolha uma base que você tenha utilizado recentemente no trabalho e a partir da qual você tenha gerado algum gráfico no excel ou outro software. Tente reproduzir dois ou três gráficos utilizando o pacote ggplot2. Não se esqueça de procurar ajuda na internet, principalmente no Stack Overflow e na documentação do pacote, além da apostila.

  2. Nos gráficos do exercício 1, há algum aspecto que você gostaria de melhorar? Pesquise sobre como fazê-lo utilizando ggplot2.

  3. Sofistique seu gráfico do ggplot2 pro meio da função ggplotly(objeto_criado_com_ggplot2) do pacote plotly. Você pode tornar o seu gráfico interativo e também construir outros gráficos diferentes com plotly.