Visualizações

Introdução

Agora que já temos em mãos as ferramentas para importar, arrumar e transformar os nossos dados, é hora de começarmos a extrair informações deles. Seguindo o nosso bom e velho ciclo da ciência de dados, o próximo passo é a construção de visualizações.

plot of chunk unnamed-chunk-9

A visualização dos dados é uma etapa importantíssima da análise estatística, pois é a partir dela que criamos a intuição necessária para escolher o teste ou modelo mais adequado para o nosso problema.

Visualizações podem ser uma simples medida resumo (frequência, média, variância, mínimo, máximo, …), um conjunto dessas medidas organizadas em uma tabela ou a representação (de uma parte) dos dados em um gráfico. Nesse tópico, focaremos na construção de gráficos, uma tarefa que, apesar de nem sempre ser conceitualmente ou tecnicamente trivial, é muito facilitada pelas ferramentas disponíveis no R.

Mas antes de mais nada, o que é um gráfico estatístico?

O que é um gráfico?

A construção de gráficos no R foi revolucionada com a criação do pacote ggplot2, fruto da tese de doutorado de Hadley Wickham. Essa revolução teve base na filosofia adotada por Hadley ao definir o que deveria ser um gráfico estatístico.

Mas será que podemos definir formalmente o que é um gráfico estatístico? Graças ao estatístico norte-americano Leland Wilkinson, a resposta é sim.

Em 2005, Leland publicou o livro The Grammar of graphics, uma fonte de princípios fundamentais para a construção de gráficos estatísticos. No livro, ele defende que um gráfico é o mapeamento dos dados a partir de atributos estéticos (posição, cor, forma, tamanho) de objetos geométricos (pontos, linhas, barras, caixas).

A partir dessa definição, Hadley escreveu A Layered Grammar of Graphics, sugerindo que os principais aspectos de um gráfico (dados, sistema de coordenadas, rótulos e anotações) podiam ser divididos em camadas, construídas uma a uma na elaboração do gráfico. Essa é a essência do ggplot2.

Além de uma filosofia bem fundamentada, o ggplot2 ainda traz outras vantagens em relação aos gráficos do r base:

  • gráficos naturalmente mais bonitos;
  • muito mais fácil deixar o gráfico do jeito que você quer;
  • a estrutura padronizada das funções deixa o aprendizado muito mais intuitivo; e
  • é possível criar uma imensa gama de gráficos com poucas linhas de código.

Para discutir os principais aspectos da construção de gráficos com o ggplot2, vamos utilizar inicialmente a base disponível no objeto mtcars. Essa base de 1974 contém dados extraídos da revista Motor Trend US sobre o consumo de combustível e características de performance e engenharia de 32 automóveis.

Se você não está familiarizado com esta base, rode help(mtcars) para mais informações.

Na próxima seção, vamos conhecer as principais funções do ggplot2 e começar a construir nossos primeiros gráficos. Não se esqueça de instalar e carregar o pacote antes de tentar rodas os exemplos.

install.packages("ggplot2")
library(ggplot2)

As camadas de um gráfico

No ggplot2, os gráficos são construídos camada por camada (ou, layers, em inglês), sendo a primeira delas dada pela função ggplot() (repare que não tem o “2”). Essa função recebe um data frame e cria a camada base do gráfico. Se rodarmos apenas a função ggplot(), obteremos um painel em branco.

ggplot(data = mtcars)

plot of chunk unnamed-chunk-12

Apesar de termos passados os dados para a função, precisamos especificar como as observações serão mapeadas nos aspectos visuais do gráfico e quais formas geométricas serão utilizadas para isso. Cada camada do gráfico representará um tipo de mapeamento ou personalização. O código abaixo é um exemplo de um gráfico bem simples, construído a partir das duas principais camadas.

ggplot(data = mtcars) + 
  geom_point(mapping = aes(x = disp, y = mpg))

plot of chunk grafico1

A figura gerada pelo código acima é um gráfico de dispersão. Observe que:

  • como vimos, a primeira camada é dada pela função ggplot() e recebe um data frame;
  • a segunda camada é dada pela função geom_point(), especificando a forma geométrica utilizada no mapeamento das observações;
  • as camadas são somadas com um +;
  • o mapeamento na função geom_point() recebe a função aes(), responsável por descrever como as variáveis serão mapeadas nos aspectos visuais da forma geométrica escolhida, no caso, pontos.

A combinação da função ggplot() e de uma ou mais funções geom_() definirá o tipo de gráfico gerado.

Cuidado

As camadas dos gráficos são empilhadas utilizando-se o sinal +. Como a estrutura é muito parecida com uma pipe line, é comum trocarmos o + por um %>% no meio do código.

Podemos acrescentar uma terceira camada ao gráfico, agora com uma personalização. Repare como é simples acrescentar labels ao gráfico com a função labs().

ggplot(data = mtcars) + 
  geom_point(mapping = aes(x = disp, y = mpg)) +
  labs(x = "Cilindradas", y = "Milhas/galão")

plot of chunk unnamed-chunk-13

Agora que você já sabe como a estrutura de camadas do ggplot funciona, vamos estudar com mais atenção para que serve a função aes().


Aesthetics

O papel da função aes() (de aesthetics, estética em inglês) é indicar a relação entre os dados e cada aspecto visual do gráfico, como qual variável será representada no eixo x, qual será representada no eixo y, a cor e o tamanho dos componentes geométricos etc. Os aspectos que podem ou devem ser mapeados depende do tipo de gráfico que você está construindo.

No exemplo anterior, atribuímos aspectos de posição: ao eixo y mapeamos a variável mpg (milhas por galão) e ao eixo x a variável disp (cilindradas). Note que os valores dos labels não são mapeados por variáveis, mas sim diretamente especificados.

Outro aspecto que pode ser mapeado nesse gráfico é a cor dos pontos:

ggplot(data = mtcars) + 
  geom_point(mapping = aes(x = disp, y = mpg, color = as.factor(am)))

plot of chunk mapear_am

Agora, a variável am (tipo de transmissão) foi mapeada à cor dos pontos, com pontos vermelhos correspondendo à transmissão automática (valor 0) e pontos azuis à transmissão manual (valor 1). Observe que inserimos a variável am como um fator, pois temos interesse apenas nos valores “0” e “1”. No entanto, também podemos mapear uma variável contínua à cor dos pontos:

ggplot(mtcars) + 
  geom_point(mapping = aes(x = disp, y = mpg, colour = cyl))

plot of chunk mapear_cor

Aqui, o número de cilindros, cyl, é representado pela tonalidade da cor azul. Note que, por padrão, a legenda é inserida automaticamente ao gráfico.

Também podemos mapear o tamanho dos pontos a uma variável de interesse:

ggplot(mtcars) +
  geom_point(mapping = aes(x = disp, y = mpg, color = cyl, size = wt))

plot of chunk mapear_tamanaho

Segue abaixo uma lista dos aspectos visuais mais utilizados:

  • color=: altera a cor de formas que não têm área (pontos e retas).
  • fill=: altera a cor de formas com área (barras, caixas, densidades, áreas).
  • size=: altera o tamanho de formas.
  • type=: altera o tipo da forma, geralmente usada para pontos.
  • linetype=: altera o tipo da linha.

Até agora, sempre mapeamos um aspecto estético a uma variável. Muitas vezes queremos apenas modificar um aspecto sem mapeá-lo a variáveis. Por exemplo, no gráfico a seguir, modificamos a cor de todos os pontos.

ggplot(mtcars, aes(y = mpg, x = disp)) + 
  geom_point(color = "red")

plot of chunk unnamed-chunk-14

A principal diferença aqui é que especificamos o argumento color= fora da função aes(). Dessa forma, podemos controlar todos os aspectos de uma forma geométrica.

ggplot(mtcars, aes(y = mpg, x = disp)) + 
  geom_point(colour = "red", size = 2, shape = 3, alpha = 0.5)

plot of chunk unnamed-chunk-15


Geoms

Os geoms definem qual forma geométrica será utilizada para a visualização das observações. Como já vimos, a função geom_point() gera gráficos de dispersão transformando pares $(x,y)$ em pontos. Veja a seguir outros geoms bastante utilizados:

  • geom_line - para linhas definidas por pares (x,y).
  • geom_abline - para retas definidas por um intercepto e uma inclinação.
  • geom_hline - para retas horizontais.
  • geom_bar - para barras.
  • geom_histogram - para histogramas.
  • geom_boxplot - para boxplots.
  • geom_density - para densidades.
  • geom_area - para áreas.

Veja a seguir como é fácil gerar diversos gráficos diferentes utilizando a mesma estrutura do gráfico de dispersão acima:

ggplot(mtcars) + 
  geom_boxplot(aes(x = as.factor(cyl), y = mpg))

plot of chunk unnamed-chunk-16

Note que para fazer um boxplot para cada grupo, precisamos passar um fator para o aspecto x do gráfico.

ggplot(mtcars) + 
  geom_histogram(aes(x = mpg))
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

plot of chunk unnamed-chunk-17

Enquanto o gráfico e dispersão demandam o mapeamento das posições x e y, o histograma requer apenas a posição x, já que, pela definição do gráfico, o eixo mostra a frequência de cada classe. O mesmo acontece com o gráfico de barras:

ggplot(mtcars) + 
  geom_bar(aes(x = as.factor(cyl)))

plot of chunk unnamed-chunk-18

Exercício: explorar novos geom()’s e mexer nos mapeamentos estéticos desses novos gráficos. Essa é uma boa referência.

Um padrão para os gráficos

Você deve ter percebido que, para fazer um gráfico usando `ggplot2` e a gramática dos gráficos, existe um padrão:

ggplot(data = DATA) + GEOM_FUNCTION(mapping = aes(MAPPINGS))

Para fazer um gráfico, basta substituir DATA por um banco de dados, GEOM_FUNCTION por uma função geométrica e MAPPINGS por uma coleção de mapas estéticos. Isso será muito útil quando você for fazer o seu próprio gráfico.

Agora, considere os 2 gráficos a seguir.

# esquerda
ggplot(mtcars) + 
  geom_point(aes(y = mpg, x = disp))
# direita
ggplot(mtcars) + 
  geom_smooth(aes(y = mpg, x = disp))

plot of chunk duplochunkplot of chunk duplochunk

Os gráficos são similares e se completam. O da esquerda, mostra como os pontos estão distribuídos, indicando uma relação entre as cilindradas e o consumo de gasolina. Já o gráfico da direita resume essa relação com uma curva de tendência e sua margem de confiança.

Como o ggplot2 é pensado para que cada gráfico seja feito como uma combinação de camadas, é muito fácil sobrepor esses dois gráficos.

ggplot(mtcars) + 
  geom_point(aes(y = mpg, x = disp)) +
  geom_smooth(aes(y = mpg, x = disp))
## `geom_smooth()` using method = 'loess'

plot of chunk unnamed-chunk-19

Desta forma, sobrepusemos os pontos e a linha de suavização. No entanto, duplicamos alguns trechos no nosso código, o que geralmente não é bom. Imagine se você precisar mudar a variável do eixo y, você precisará trocar o nome da variável em mais de um lugar do código. Para resolver isso, você pode definir o mapping apenas uma vez dentro da declaração do gráfico, conforme o código a seguir.

ggplot(mtcars, aes(y = mpg, x = disp)) + 
  geom_point() +
  geom_smooth()
## `geom_smooth()` using method = 'loess'

plot of chunk unnamed-chunk-20

Veja que isso gera o mesmo gráfico!

Veja que mesmo com dois geom’s, o ggplot segue a mesma regra para mapear as variáveis para os aspectos visuais. Por exemplo, se você mapear uma variável para a cor, você obterá o seguinte gráfico.

ggplot(mtcars, aes(y = mpg, x = disp, colour = as.factor(cyl))) + 
  geom_point() +
  geom_smooth(method = "lm")

plot of chunk unnamed-chunk-21

O ggplot2 agora desenhou uma reta para cada um dos grupos de pontos e coloriu cada grupo de pontos de uma cor diferente. Em alguns casos, você pode querer mapear a cor em apenas uma das camadas do gráfico. Isso pode ser feito da seguinte forma:

ggplot(mtcars, aes(y = mpg, x = disp)) + 
  geom_point(aes(colour = as.factor(cyl))) +
  geom_smooth(method = "lm")

plot of chunk unnamed-chunk-22

Agora, cada grupo de pontos tem uma cor, mas a reta é única para todos os pontos.


Facets

Uma funcionalidade muito útil do ggplot2 é a possibilidade de usar facets. Isso auxilia na visualização de diferentes subconjuntos dos dados em gráficos separados, permitindo a visualização de comportamentos diferentes dependendo do grupo.

ggplot(mtcars, aes(y = mpg, x = disp)) + 
  geom_point() +
  geom_smooth(method = "lm") + 
  facet_wrap(~am)

plot of chunk unnamed-chunk-23

No gráfico acima, rapidamente conseguimos visualizar que se o carro não é automático o consumo de combustível é muito menor do que quando o carro é automático. Também conseguimos ver que a inclinação das retas é bem diferente dependendo do carro ser automático/manual.

Exercício: pesquisar o que faz a função facet_grid().


Personalizando

Como exemplo de personalização de um gráfico com o ggplot2, vamos partir de um simples boxplot e fazer diversas alterações nas legendas.

Para isso, utilizaremos nessa seção a base contida no objeto PlantGrowth, contendo resultados de um experimento para comparar o crescimento de plantas sob três condições diferentes (um controle e dois tratamentos). Para mais informações, rode help(PlantGrowth).

O gráfico inicial é construído da seguinte forma:

bp <- ggplot(data = PlantGrowth, aes(x = group, y = weight, fill = group)) +
  geom_boxplot()

bp

plot of chunk unnamed-chunk-24

Removendo totalmente a legenda

Existem diversas maneiras para remover a legenda de um gráfico no ggplot2. A forma mais simples é usar guides(fill = FALSE) com fill sendo o atributo gráfico do qual você deseja remover a legenda.

bp + guides(fill = FALSE)

plot of chunk unnamed-chunk-25

Também é possível remover a legenda utilizando a função scale_fill_discrite(). A família scale_X_Y() de funções permite escolher manualmente os parâmetros de cada escala utilizada no gráfico.

bp + scale_fill_discrete(guide = F)

plot of chunk unnamed-chunk-26

O comando a seguir remove todas as legendas, não importa o atributo que ela esteja representando.

bp + theme(legend.position="none")

plot of chunk unnamed-chunk-27

Alterando a ordem dos itens

Para alterar a ordem dos itens na legenda do gráfico no ggplot2, usamos o comando da escala de cores.

bp + scale_fill_discrete(breaks=c("trt1", "ctrl", "trt2"))

plot of chunk unnamed-chunk-28

bp

plot of chunk unnamed-chunk-28

Dependendo dos aspectos gráficos (cores, formatos, preenchimentos) especificados, você pode precisar usar alguma das seguintes funções:

  • scale_fill_manual()
  • scale_colour_hue()
  • scale_colour_manual()
  • scale_shape_discrete()
  • scale_linetype_discrete()

Você pode também querer inverter a ordem dos itens da legenda. Isso pode ser feito de uma das seguintes maneiras.

bp + guides(fill = guide_legend(reverse = TRUE))
bp + scale_fill_discrete(guide = guide_legend(reverse = TRUE))

plot of chunk unnamed-chunk-29plot of chunk unnamed-chunk-29

Removendo os títulos da legenda

Algumas vezes é necessário remover o título das legendas do gráfico feito no ggplot2. Veja a seguir algumas maneiras:

# Remove o título apenas da legenda do preenchimento (fill).
bp + guides(fill=guide_legend(title=NULL))

# Remove o título de todas as legendas.
bp + theme(legend.title = element_blank())

plot of chunk unnamed-chunk-30plot of chunk unnamed-chunk-30

Modificando texto, cores e rótulos

Existem duas formas para modificar os textos e rótulos das legendas. Uma delas é modificar o data.frame de forma com que os fatores tenham o mesmo nome que você deseja na legenda. Outra forma é usando as funções scale_X_Y().

No nosso exemplo, como a variável group está associada ao atributo fill, usamos as funções scale_fill_discrete(). e scale_fill_manual(). Utilizamos a primeira se não quisermos alterar as cores padrão, mas sim que cada fator esteja associado uma cor diferente. Mudamos também os rótolos e o título da legenda.

bp + scale_fill_discrete(name = "Experimental\nCondition",
                         breaks = c("ctrl", "trt1", "trt2"),
                         labels = c("Control", "Treatment 1", "Treatment 2"))

plot of chunk unnamed-chunk-31

Usamos a segunda se quisermos alterar as cores padrão. Aqui, escolhemos as cores da escala hexadecimal. Veja que isso não aletrou o eixo x do gráfico.

bp + scale_fill_manual(values=c("#999999", "#E69F00", "#56B4E9"), 
                       name="Experimental\nCondition",
                       breaks=c("ctrl", "trt1", "trt2"),
                       labels=c("Control", "Treatment 1", "Treatment 2"))

plot of chunk unnamed-chunk-32

Modificando a aparência da legenda

Existem inúmeras modificações que podem ser realizadas na aparência da legenda. Todas elas estão relacionadas à modificação do element_text(). Veja neste link todos os atributos que podem ser modificados.

# Mudando a aparência do título
bp + theme(legend.title = element_text(color = "blue", size = 16, face = "bold"))

plot of chunk unnamed-chunk-33

# Mudando a aparência dos rótulos
bp + theme(legend.text = element_text(colour = "blue", size = 16, face = "bold"))

plot of chunk unnamed-chunk-34

Modificando a posição da legenda

É possível controlar a posição da legenda facilmente escolhendo uma das posições: left, right, top e bottom.

bp + theme(legend.position="top")

plot of chunk unnamed-chunk-35

Também é possível controlar a posição da legenda de forma precisa usando a função theme(). A legenda será posicionada dentro do gráfico com o ponto central sendo o valor do argumento legend.position=. Esses valores são definidos de forma que o ponto (0,0) seja o canto inferior esquerdo e (1,1) seja o canto superior direito.

bp + theme(legend.position=c(.5, .5))

plot of chunk unnamed-chunk-36


Exercícios


1.

O que tem de errado no código abaixo? Por que os pontos não ficaram azuis?

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = "blue"))

plot of chunk unnamed-chunk-37


2.

Mapeie uma variável contínua para uma cor, tamanho e forma. Como essas formas estéticas se comportam diferente para variáveis categóricas vs contínuas?


3.

O que acontece se você rodar ggplot(data = mtcars)?


4.

Utilizando o mtcars, faça um gráfico de dispersão de mpg por qsec.


5.

Utilizando o mtcars, o que acontece se você fizer um gráfico de dispersão de vs por mpg? Por que o gráfico não é útil?