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.

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)

Caso não seja possível instalar o ggplot, é possível simular os scripts em: https://rdrr.io/snippets/

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)

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))

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.

Atenção

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")

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)))

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))

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))

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")

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)

head(mpg)
## # A tibble: 6 x 11
##   manufacturer model displ  year   cyl trans      drv     cty   hwy fl    class 
##   <chr>        <chr> <dbl> <int> <int> <chr>      <chr> <int> <int> <chr> <chr> 
## 1 audi         a4      1.8  1999     4 auto(l5)   f        18    29 p     compa…
## 2 audi         a4      1.8  1999     4 manual(m5) f        21    29 p     compa…
## 3 audi         a4      2    2008     4 manual(m6) f        20    31 p     compa…
## 4 audi         a4      2    2008     4 auto(av)   f        21    30 p     compa…
## 5 audi         a4      2.8  1999     6 auto(l5)   f        16    26 p     compa…
## 6 audi         a4      2.8  1999     6 manual(m5) f        18    26 p     compa…
ggplot(data = mpg) +
 geom_point(mapping = aes(x = displ, y = hwy, color = class))

### Customização por forma:

ggplot(data = mpg) +
 geom_point(mapping = aes(x = displ, y = hwy, shape = class))
## Warning: The shape palette can deal with a maximum of 6 discrete values because
## more than 6 becomes difficult to discriminate; you have 7. Consider
## specifying shapes manually if you must have them.
## Warning: Removed 62 rows containing missing values (geom_point).

Customização por cor e forma:

ggplot(data = mpg) +
 geom_point(mapping = aes(x = displ, y = hwy, shape = class, color = class))
## Warning: The shape palette can deal with a maximum of 6 discrete values because
## more than 6 becomes difficult to discriminate; you have 7. Consider
## specifying shapes manually if you must have them.
## Warning: Removed 62 rows containing missing values (geom_point).

Trabalhando com FACETS:

ggplot(data = mpg) +
 geom_point(mapping = aes(x = displ, y = hwy, color = displ)) +
 facet_wrap(~ class, nrow = 2)

ggplot(data = mpg) +
 geom_point(mapping = aes(x = displ, y = hwy, color = displ)) +
 facet_grid(drv ~ cyl)

Regressões

Adicionando intervalode confiança

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

ggplot(data = mpg) +
 geom_smooth(mapping = aes(x = displ, y = hwy))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg) +
 geom_smooth(mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(x = displ, y = hwy, color = drv))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg) +
 geom_smooth(mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(x = displ, y = hwy))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg) +
 geom_smooth(mapping = aes(x = displ, y = hwy))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg) +
 geom_smooth(mapping = aes(x = displ, y = hwy, group = drv))
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg) +
 geom_smooth(
 mapping = aes(x = displ, y = hwy, color = drv),
 show.legend = FALSE
 )
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
 geom_point(mapping = aes(color = class)) +
 geom_smooth()
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
 geom_point(mapping = aes(color = class)) +
 geom_smooth(
 data = mpg[mpg$class=="subcompact", ],
 se = FALSE
 )
## `geom_smooth()` using method = 'loess' and formula 'y ~ x'

head(diamonds)
## # A tibble: 6 x 10
##   carat cut       color clarity depth table price     x     y     z
##   <dbl> <ord>     <ord> <ord>   <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23  Ideal     E     SI2      61.5    55   326  3.95  3.98  2.43
## 2 0.21  Premium   E     SI1      59.8    61   326  3.89  3.84  2.31
## 3 0.23  Good      E     VS1      56.9    65   327  4.05  4.07  2.31
## 4 0.290 Premium   I     VS2      62.4    58   334  4.2   4.23  2.63
## 5 0.31  Good      J     SI2      63.3    58   335  4.34  4.35  2.75
## 6 0.24  Very Good J     VVS2     62.8    57   336  3.94  3.96  2.48
ggplot(data = diamonds) +
 geom_bar(mapping = aes(x = cut))

O algoritimo que calcula os novos valores se chama stat (short for statistical transformation) e funciona como a ilustração abaixo:

\label{fig:figs} Conjuntos

Conjuntos

ggplot(data = diamonds) +
 stat_summary(
 mapping = aes(x = cut, y = depth),
 fun.ymin = min,
 fun.ymax = max,
 fun.y = median
 )

ggplot(data = diamonds) +
 geom_bar(mapping = aes(x = cut, y = ..prop..))

ggplot(data = diamonds) +
 geom_bar(
 mapping = aes(x = cut, fill = color, y = ..prop..)
 )

ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, color = cut))

ggplot(data = diamonds) +
 geom_bar(mapping = aes(x = cut, fill = cut))

ggplot(data = diamonds) +
 geom_bar(mapping = aes(x = cut, fill = clarity))

ggplot( 
 data = diamonds,
 mapping = aes(x = cut, fill = clarity)
) +
 geom_bar(alpha = 1/5, position = "identity")

ggplot(
 data = diamonds,
 mapping = aes(x = cut, color = clarity)
) +
 geom_bar(fill = NA, position = "identity")

ggplot(data = diamonds) +
  geom_bar(
    mapping = aes(x = cut, fill = clarity),
    position = "fill"
  )

ggplot(data = diamonds) +
  geom_bar(
    mapping = aes(x = cut, fill = clarity),
    position = "dodge"
  )

ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
  geom_point()

ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
  geom_boxplot()

ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
  geom_boxplot() +
  coord_flip()

bar <- ggplot(data = diamonds) +
  geom_bar(
    mapping = aes(x = cut, fill = cut),
    show.legend = FALSE,
    width = 1
  ) +
  theme(aspect.ratio = 1) +
  labs(x = NULL, y = NULL)
bar + coord_flip()

bar + coord_polar()

Cores

df <- data.frame(x = c("a", "b", "c", "d"), y = c(3, 4, 1, 2))
bars <- ggplot(df, aes(x, y, fill = x)) +
  geom_bar(stat = "identity") +
  labs(x = NULL, y = NULL) 

bars

bars + scale_fill_hue(c = 40)

bars + scale_fill_hue(h = c(180, 300))

bars + scale_fill_brewer(palette = "Set1")

bars + scale_fill_brewer(palette = "Set2")

bars + scale_fill_brewer(palette = "Accent")

bars + scale_fill_grey()

bars + scale_fill_grey(start = 0.5, end = 1)

bars + scale_fill_grey(start = 0, end = 0.5)

library(wesanderson)
names(wes_palettes)
##  [1] "BottleRocket1"  "BottleRocket2"  "Rushmore1"      "Rushmore"      
##  [5] "Royal1"         "Royal2"         "Zissou1"        "Darjeeling1"   
##  [9] "Darjeeling2"    "Chevalier1"     "FantasticFox1"  "Moonrise1"     
## [13] "Moonrise2"      "Moonrise3"      "Cavalcanti1"    "GrandBudapest1"
## [17] "GrandBudapest2" "IsleofDogs1"    "IsleofDogs2"
bars + scale_fill_manual(values = wes_palette("BottleRocket1"))

bars + scale_fill_manual(values = wes_palette("FantasticFox1"))

bars + scale_fill_manual(values = wes_palette("Rushmore"))