Este notebook traz os principais pontos abordados no Capítulo 1 do livro R for Data Science, lançado pela O’Reilly em 2023.
Todos os códigos demonstrados pelo autor estão replicados aqui, bem como resoluções dos exercícios. Claro que não tenho como garantir que as resoluções estão corretas, mas deixei respostas honestas e me esforcei ao máximo para responder de forma correta, e apesar de não ser um gabarito, é um ponto de vista que poderá dialogar com suas próprias soluções.
Ao longo dos pedaços de código, deixei algumas linhas comentadas (iniciando com #), não esqueça de remover os # para que seu código funcione.
Os títulos de seções e subseções do livro são reproduzidos aqui (apenas traduzidos para o português), então caso queira sair de algum ponto específico deste resumo e dar uma olhada em como está o texto original, basta procurar pela seção do livro no qual o ponto que você busca se encontra.
Caso você encontre algum erro de digitação ou teórico, ou só queira comentar o material, mande um e-mail para aksfelix@gmail.com com o assunto “R4DS”.
Você precisará dos seguintes pacotes para rodar todos os códigos e realizar seus exercícios, para instalá-los, basta copiar os seguintes comandos no seu console:
#install.packages("tidyverse")
#install.packages("palmerpenguins")
#install.packages("ggthemes")
Uma vez instalados, é preciso visitar sua biblioteca de pacotes e ativá-los:
library(tidyverse)
library(palmerpenguins)
library(ggthemes)
Um pouco sobre o que traz cada pacote:
Temos algumas opções de comandos para ver um resumo dos dados contidos dentro de um Data Frame, você pode tentar este:
palmerpenguins::penguins
## # A tibble: 344 × 8
## species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
## <fct> <fct> <dbl> <dbl> <int> <int>
## 1 Adelie Torgersen 39.1 18.7 181 3750
## 2 Adelie Torgersen 39.5 17.4 186 3800
## 3 Adelie Torgersen 40.3 18 195 3250
## 4 Adelie Torgersen NA NA NA NA
## 5 Adelie Torgersen 36.7 19.3 193 3450
## 6 Adelie Torgersen 39.3 20.6 190 3650
## 7 Adelie Torgersen 38.9 17.8 181 3625
## 8 Adelie Torgersen 39.2 19.6 195 4675
## 9 Adelie Torgersen 34.1 18.1 193 3475
## 10 Adelie Torgersen 42 20.2 190 4250
## # ℹ 334 more rows
## # ℹ 2 more variables: sex <fct>, year <int>
Ou, você pode simplesmente digitar:
penguins
## # A tibble: 344 × 8
## species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g
## <fct> <fct> <dbl> <dbl> <int> <int>
## 1 Adelie Torgersen 39.1 18.7 181 3750
## 2 Adelie Torgersen 39.5 17.4 186 3800
## 3 Adelie Torgersen 40.3 18 195 3250
## 4 Adelie Torgersen NA NA NA NA
## 5 Adelie Torgersen 36.7 19.3 193 3450
## 6 Adelie Torgersen 39.3 20.6 190 3650
## 7 Adelie Torgersen 38.9 17.8 181 3625
## 8 Adelie Torgersen 39.2 19.6 195 4675
## 9 Adelie Torgersen 34.1 18.1 193 3475
## 10 Adelie Torgersen 42 20.2 190 4250
## # ℹ 334 more rows
## # ℹ 2 more variables: sex <fct>, year <int>
Ou ainda, para um resumo um pouco mais organizado:
glimpse(penguins)
## Rows: 344
## Columns: 8
## $ species <fct> Adelie, Adelie, Adelie, Adelie, Adelie, Adelie, Adel…
## $ island <fct> Torgersen, Torgersen, Torgersen, Torgersen, Torgerse…
## $ bill_length_mm <dbl> 39.1, 39.5, 40.3, NA, 36.7, 39.3, 38.9, 39.2, 34.1, …
## $ bill_depth_mm <dbl> 18.7, 17.4, 18.0, NA, 19.3, 20.6, 17.8, 19.6, 18.1, …
## $ flipper_length_mm <int> 181, 186, 195, NA, 193, 190, 181, 195, 193, 190, 186…
## $ body_mass_g <int> 3750, 3800, 3250, NA, 3450, 3650, 3625, 4675, 3475, …
## $ sex <fct> male, female, female, NA, female, male, female, male…
## $ year <int> 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007, 2007…
Ainda há a opção de abrir uma tabela iterativa (exclusivamente no RStudio) - não se esqueça de remover o # do início da linha de código:
#View(penguins)
Para saber mais sobre este pacote ou qualquer outro pacote no R:
#?penguins
Vamos agora gerar algumas visualizações para estes dados. Veja o que cada comando do ggplot faz, vamos adicionando camadas nos plots aos poucos para visualizarmos o que cada um dos comandos traz de novo à imagem gerada. Observe:
ggplot(data = penguins)
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g))
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point()
Dica: para abreviar e deixar nosso código mais curto. Podemos escrever o mesmo comando acima suprimindo o nome dos argumentos da função:
ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point()
Também há um recurso chamado “pipe”, que eu ainda não conheço bem o conceito, mas que permite que o código seja escrito assim:
penguins |>
ggplot(aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point()
Vamos continuar adicionando camadas e vendo o que cada parte adicionada do código traz de novidade ao nosso plot:
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
) +
geom_point()
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g, color = species)
) +
geom_point() +
geom_smooth(method = "lm")
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(mapping = aes(color = species)) +
geom_smooth(method = "lm")
Geralmente, não é uma boa ideia representar informações usando apenas cores em um gráfico, pois algumas pessoas percebem cores de uma forma diferente, devido a daltonismo ou condições similares. Para isso, o autor reforça que é uma boa prática trabalhar com formas diferentes para representar dados no scatterplot:
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(mapping = aes(color = species, shape = species)) +
geom_smooth(method = "lm")
Continuando com a adição de camadas ao nosso ggplot, agora daremos nomes mais adequados a todos os elementos do nosso plot:
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(aes(color = species, shape = species)) +
geom_smooth(method = "lm") +
labs(
title = "Body mass and flipper length",
subtitle = "Dimensions for Adeliem Chinstrap, and Gentoo Penguins",
x = "Flipper length (mm)",
y = "Body mass (g)",
color = "Species",
shape = "Species") +
scale_color_colorblind()
1. How many rows are in penguins? How many columns?
Linhas: 344
Colunas: 8
2. What does the bill_depth_mm variable in the penguins data frame describe? Read the help for ?penguins to find out.
Executando o comando de ajuda (?penguins), podemos encontrar o texto exigido para responder à questão:
“A number denoting bill depth (millimeters).”
3. Make a scatterplot of bill_depth_mm versus bill_length_mm. That is, make a scatterplot with bill_depth_mm on the y-axis and bill_length_mm on the x-axis. Describe the relationship between these two variables.
ggplot(
data = penguins,
mapping = aes(x = bill_length_mm, y = bill_depth_mm)
) +
geom_point(aes(color = species, shape = species)) +
geom_smooth(method = "lm") +
labs(
title = "Bill depth and length",
subtitle = "Dimensions for Adeliem Chinstrap, and Gentoo Penguins",
x = "Bill length (mm)",
y = "Bill depth (mm)",
color = "Species",
shape = "Species") +
scale_color_colorblind()
Todas as espécies parecem trazer uma relação forte entre o tamanho e a largura do, o que não pode ser notado ao olharmos o plot de todos os pinguins sem distinção de espécie.
4.What happens if you make a scatterplot of species versus bill_depth_mm? What might be a better choice of geom?
ggplot(
data = penguins,
mapping = aes(x = bill_depth_mm, y = species)
) +
geom_point(aes(color = species, shape = species)) +
geom_smooth(method = "lm") +
labs(
title = "Species and bill depth",
subtitle = "Dimensions for Adeliem Chinstrap, and Gentoo Penguins",
x = "Bill depth (mm)",
y = "Species",
color = "Species",
shape = "Species") +
scale_color_colorblind()
Os pontos não estão muito espalhados, acredito que um plot em barras seria mais adequado para esta visualização.
5. Why does the following give and error, and how would you fix it?
#ggplot(data = penguins) +
# geom_point()
“geom_point()” requer uma definição para x e y no argumento aes. Neste caso poderíamos mudar a primeira linha para algo como:
“ggplot(data = penguins, aes(x = bill_depth_mm, y = species)) +”
6. What does the na.rm argument do in geom_point()? What is the default value of the argument? Create a scatterplot where you successfully use this argument set to TRUE.
O default desse argumento é o valor FALSE, onde os valores faltantes (missing values), são removidos e um aviso (warning) é emitido. Se o valor for convertido para TRUE, os valores faltantes são removidos sem que um aviso seja emitido.
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(aes(color = species, shape = species), na.rm = TRUE) +
geom_smooth(method = "lm", na.rm = TRUE) +
labs(
title = "Body mass and flipper length",
subtitle = "Dimensions for Adeliem Chinstrap, and Gentoo Penguins",
x = "Flipper length (mm)",
y = "Body mass (g)",
color = "Species",
shape = "Species") +
scale_color_colorblind()
7. Add the following caption to the plot you made in the previous exercise: “Data come from the palmerpenguins package.” Hint: Take a look at the documentation for labs().
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(aes(color = species, shape = species), na.rm = TRUE) +
geom_smooth(method = "lm", na.rm = TRUE) +
labs(
title = "Body mass and flipper length",
subtitle = "Dimensions for Adeliem Chinstrap, and Gentoo Penguins",
x = "Flipper length (mm)",
y = "Body mass (g)",
color = "Species",
shape = "Species",
caption = "Data come from the palmerpenguins package.") +
scale_color_colorblind()
8. Re-create the following visualization. What aesthetic should bill_depth_mm be mapped to? And should it be mapped at the global level or at the geom level?
ggplot(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
) +
geom_point(mapping = aes(color = bill_depth_mm)) +
geom_smooth(method = "loess")
9. Run this code in your head and predict what the output will look like. Then, run the code in R and check your predictions.
ggplot(data = penguins, mapping = aes (x = flipper_length_mm, y = body_mass_g, color = island))+
geom_point() +
geom_smooth (se = FALSE))
A sombra do nível de confiança sumirá.
ggplot(
data = penguins,
mapping = aes (x = flipper_length_mm, y = body_mass_g, color = island)
)+
geom_point() +
geom_smooth (se = FALSE)
10. Will these two graphs look different? Why/why not?
ggplot( data = penguins, mapping = aes (x = flipper_length_mm, y = body_mass_g) )+
geom_point()+
geom_smooth()
ggplot() +
geom_point( data = penguins, mapping = aes(x = flipper_length_mm, y = body_mass_g) )+
geom_smooth(data = penguins, mapping = aes(x = flipper_length_mm, y = body_mass_g) )
Acho que sim, mas não tenho certeza.
ggplot(
data = penguins,
mapping = aes (x = flipper_length_mm, y = body_mass_g)
)+
geom_point()+
geom_smooth()
ggplot()+
geom_point(
data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
)+
geom_smooth(data = penguins,
mapping = aes(x = flipper_length_mm, y = body_mass_g)
)
Após a execução é possível ver que ambos os códigos geram plots iguais.
Nesta seção o autor passar por cada tipo de variável mostrando quais as maneiras mais comuns de representá-las.
Variáveis categóricas são geralmente representadas em barras:
ggplot(penguins, aes(x = species)) +
geom_bar()
R lida melhor com variáveis categóricas se elas forem transformadas em fator. Para ordenar as variáveis de acordo com sua frequência, usamos o argumento fct_infreq:
ggplot(penguins, aes(x = fct_infreq(species))) +
geom_bar()
Variáveis numéricas são geralmente representadas por histogramas:
ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 200)
Ao fazer um gráfico de histograma, é útil testar diversas larguras do agrupamento de dados, para entender qual gráfico nos ajuda a identificar padrões de distribuição, exemplo:
ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 20)
ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 200)
ggplot(penguins, aes(x = body_mass_g)) +
geom_histogram(binwidth = 2000)
Se a distribuição for suave, podemos usar também um plot de densidade:
ggplot(penguins, aes(x = body_mass_g)) +
geom_density()
1. Make a bar plot of species of penguins, where you assign species to the y aesthetic. How is this plot different?
ggplot(penguins, aes(y = species)) +
geom_bar()
É um gráfico de barras horizontal.
2. How are the following two plots different? Which aesthetic, color or fill, is more useful for changing the color of bars?
ggplot(penguins, aes(x = species)) +
geom_bar(color = "red")
ggplot(penguins, aes(x = species)) +
geom_bar(fill = "red")
No primeiro plot, uma cor diferente é aplicada ao contorno das barras, no segundo, a cor está preenchendo as barras, o que é muito mais adequado para usos gerais de cores em gráficos de barras.
3. What does the bins argument in geom_histogram() do?
Eles determinam em quantos bins o eixo x será dividido no plot de histograma.
4. Make a histogram of the carat variable in the diamonds dataset that is available when you load the tidyverse package. Experiment with different binwidth values. What value reveals the most interesting patterns?
ggplot2::diamonds
## # A tibble: 53,940 × 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.29 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
## 7 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47
## 8 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53
## 9 0.22 Fair E VS2 65.1 61 337 3.87 3.78 2.49
## 10 0.23 Very Good H VS1 59.4 61 338 4 4.05 2.39
## # ℹ 53,930 more rows
ggplot(diamonds, aes(x = carat)) +
geom_histogram(binwidth = 2)
ggplot(diamonds, aes(x = carat)) +
geom_histogram(binwidth = 0.2)
ggplot(diamonds, aes(x = carat)) +
geom_histogram(binwidth = 0.02)
A visualização mais utilizada para entender a relação entre uma variável numérica e uma variável categórica é o boxplot.
Algumas nomenclaturas interessantes para entender o boxplot:
IQR - Interquartile Range (distância interquartis) vai do 25^o percentil até o 75^o.
Outliers - são aqueles pontos de dados que estão a mais de 1.5 vezes acima ou abaixo da IQR. Eles não são muito comuns, se aparecem muitos outliers na sua análise, repense-a, ou considere outro tipo de visualização.
A figura abaixo retirada do livro dá uma boa noção da relação entre o boxplot e outras distribuições de dados (scatterplot e histograma):
ggplot(penguins, aes(x = species, y = body_mass_g)) +
geom_boxplot()
Dá pra ver que a visualização por boxplots oferece recursos visuais superiores a uma visualização por densidade, observe:
ggplot(penguins, aes(x = body_mass_g, color = species)) +
geom_density(linewidth = 0.75)
ggplot(penguins, aes(x = body_mass_g, color = species, fill = species)) +
geom_density(alpha = 0.5)
Importante estar atento à seguinte terminologia:
As variáveis são mapeadas para o argumento aesthetics quando deseja-se que o atributo visual varie baseado nos valores das variáveis mapeadas.
Caso contrário podemos setar um valor arbitrário para os atributos de aesthetics.
A maneira mais comum de representar duas variáveis categóricas é através das barras empilhadas. Podemos ter duas variações dessa visualização. A primeira forma de visualização, mostra a contagem dos elementos, como no exemplo a seguir:
ggplot(penguins, aes(x = island, fill = species)) +
geom_bar()
A segunda forma de visualização, mostra a porcentagem de cada variável distribuída entre as categorias mapeadas no eixo x. Cada coluna, representa 100% dos valores contidos na variável representada por ela.
ggplot(penguins, aes(x = island, fill = species)) +
geom_bar(position = "fill")
A visualização mais comum para representar a relação entre duas variáveis numéricas é o scatterplot:
ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point()
A adição de mais variáveis se dá mapeando-as em aesthetics adicionais. Como no exemplo seguinte:
ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = species, shape = island))
Colocar muitas variáveis em um plot pode não ser muito útil, como no plot acima, que possui 4 variáveis. A melhor alternativa é dividí-lo em facetas, ou seja, subplots que mostram, cada um, uma parte dos dados, e juntos compõem o todo:
ggplot(penguins, aes(x = flipper_length_mm, y = body_mass_g)) +
geom_point(aes(color = species, shape = species)) +
facet_wrap(~island)
Para isso funcionar, a variável transformada em fórmula “~” precisa ser categórica.
OBS: Fórmula é um termo que, no ggplot, não tem nada a ver com “equação”.
1.The mpg data frame that is bundled with the ggplot2 package contains 234 observations collected by the US Environmental Protection Agency on 38 car models. Which variables in mpg are categorical? Which variables are numerical? (Hint: Type ?mpg to read the documentation for the dataset.) How can you see this information when you run mpg?
glimpse(mpg)
## Rows: 234
## Columns: 11
## $ manufacturer <chr> "audi", "audi", "audi", "audi", "audi", "audi", "audi", "…
## $ model <chr> "a4", "a4", "a4", "a4", "a4", "a4", "a4", "a4 quattro", "…
## $ displ <dbl> 1.8, 1.8, 2.0, 2.0, 2.8, 2.8, 3.1, 1.8, 1.8, 2.0, 2.0, 2.…
## $ year <int> 1999, 1999, 2008, 2008, 1999, 1999, 2008, 1999, 1999, 200…
## $ cyl <int> 4, 4, 4, 4, 6, 6, 6, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 8, 8, …
## $ trans <chr> "auto(l5)", "manual(m5)", "manual(m6)", "auto(av)", "auto…
## $ drv <chr> "f", "f", "f", "f", "f", "f", "f", "4", "4", "4", "4", "4…
## $ cty <int> 18, 21, 20, 21, 16, 18, 18, 18, 16, 20, 19, 15, 17, 17, 1…
## $ hwy <int> 29, 29, 31, 30, 26, 26, 27, 26, 25, 28, 27, 25, 25, 25, 2…
## $ fl <chr> "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p", "p…
## $ class <chr> "compact", "compact", "compact", "compact", "compact", "c…
Há 6 variáveis categóricas e 5 variáveis numéricas. É possível verificar essas informações usando as funções glimpse(), View(), ou simplesmente digitando os comandos mpg ou ggplot2::mpg.
2. Make a scatterplot of hwy versus displ using the mpg data frame. Next, map a third, numerical variable to color, then size, then both color and size, and then shape. How do these aesthetics behave differently for categorical versus numerical variables?
ggplot(mpg, aes(x = hwy, y = displ)) +
geom_point()
ggplot(mpg, aes(x = hwy, y = displ)) +
geom_point(aes(color = cty))
ggplot(mpg, aes(x = hwy, y = displ)) +
geom_point(aes(size = cty))
ggplot(mpg, aes(x = hwy, y = displ)) +
geom_point(aes(color = cty, size = cty))
ggplot(mpg, aes(x = hwy, y = displ)) +
geom_point(aes(shape = cty)) +
scale_shape_binned()
O aesthetic “shape” não aceita variáveis numéricas, apenas categóricas, no entando é possível distribuir as variáveis numéricas em bins usando a função scale_shape_binned, gerando a visualização acima. As demais aesthetic aceitam as variáveis numéricas sem a necessidade de uma função complementar.
3. In the scatterplot of hwy versus displ, what happens if you map a third variable to linewidth?
ggplot(mpg, aes(x = hwy, y = displ, linewidth = cty)) +
geom_point()
Não aconteceu nada aparentemente.
4. What happens if you map the same variable to multiple aesthetics?
ggplot(mpg, aes(x = hwy, y = displ, color = displ, linewidth = displ)) +
geom_point()
Não aconteceu nada demais.
5. Make a scatterplot of bill_depth_mm versus bill_length_mm and color the points by species. What does adding coloring by species reveal about the relationship between these two variables? What about faceting by species?
ggplot(penguins, aes(x = bill_depth_mm, y = bill_length_mm, color = species)) +
geom_point()
A correlação entre as duas variáveis é mais ou menos forte a dependeder da espécie.
ggplot(penguins, aes(x = bill_depth_mm, y = bill_length_mm)) +
geom_point() +
facet_wrap(~species)
As facetas melhoram a visualização intraespécie, podemos ver que a relação entre as variáveis dentro das espécies Chinstrap e Gentoo são bem parecidas entre si, e mais fortes se comparadas à espécie Adelie.
6. Why does the following yield two separate legends? How would you fix it to combine the two legends?
ggplot(
data = penguins,
mapping = aes(
x = bill_length_mm, y = bill_depth_mm,
color = species, shape = species
)
) +
geom_point() +
labs(color = "Species")
Você tem que mapear o label dentro do argumento de aesthetics.
7. Create the two following stacked bar plots. Which question can you answer with the first one? Which question can you answer with the second one?
ggplot(penguins, aes(x = island, fill = species)) +
geom_bar(position = "fill")
ggplot(penguins, aes(x = species, fill = island)) +
geom_bar(position = "fill")
Com o primeiro plot consigo dizer qual é a espécie dominante em cada uma das ilhas. Com o segundo plot consigo dizer como cada espécie está distribuída entre as diversas ilhas.
Para salvar seu último plot executado:
ggsave(filename = "penguin-plot.png")
Ou simplesmente:
ggsave("penguin-plot2.png")
1. Run the following lines of code. Which of the two plots is saved as mpg-plot.png? Why?
ggplot(mpg, aes(x = class)) +
geom_bar()
ggplot(mpg, aes(x = cty, y = hwy)) +
geom_point()
ggsave("mpg-plot.png")
O plot salvo é sempre o último a ser executado
2. What do you need to change in the previous code to save the plot as a PDF instead of a PNG? How could you find out what types of image files would work in ggsave()?
Provavelmente é só nomear o arquivo com .pdf em vez de .png, para me certificar disso e verificar quais outros formatos de arquivo de imagem são suportados eu posso procurar ajuda com o comando ?ggsave.
Esta brevíssima seção não traz nenhum conteúdo contido no livro ou mencionado pelo autor, e sim alguns links úteis com os quais me deparei ao estudar o capítulo: