3
Visualizações
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?
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/
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.
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().
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:
 ### 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).
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).
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)
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.48ggplot(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:
 
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()
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"))