Boxplots estão por toda parte, e muitas vezes são úteis quando queremos ver sumários de várias distribuições nos dados. Aqui vão algumas dicas para melhorar seu uso de boxplots no ggplot2
.
Usaremos dados sobre Star Wars incluÃdos no pacote dplyr
, que é parte do tidyverse. Os dados vem da Star Wars API e já estão no namespace se carregamos o tidyverse:
library(tidyverse)
theme_set(theme_bw())
glimpse(starwars)
## Observations: 87
## Variables: 13
## $ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", "L…
## $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188, …
## $ mass <dbl> 77.0, 75.0, 32.0, 136.0, 49.0, 120.0, 75.0, 32.0, 84.…
## $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "bro…
## $ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "lig…
## $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue", "…
## $ birth_year <dbl> 19.0, 112.0, 33.0, 41.9, 19.0, 52.0, 47.0, NA, 24.0, …
## $ gender <chr> "male", NA, NA, "male", "female", "male", "female", N…
## $ homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alderaa…
## $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human",…
## $ films <list> [<"Revenge of the Sith", "Return of the Jedi", "The …
## $ vehicles <list> [<"Snowspeeder", "Imperial Speeder Bike">, <>, <>, <…
## $ starships <list> [<"X-wing", "Imperial shuttle">, <>, <>, "TIE Advanc…
Para conhecer mais sobre essas colunas, você pode fazer help("starwars")
Para facilitar alguns exemplos, vou criar uma coluna que tem a raça dos personagens, mas apenas dizendo se é humano, androide ou outro, e uma que diz em quantos filmes o personagem apareceu.
starwars = starwars %>%
mutate(species_short = if_else(species %in% c("Human", "Droid"),
species,
"Other"),
n_films = map_dbl(films, length))
Passando nenhum parâmetro, temos o seguinte:
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = "", y = height)) +
geom_boxplot()
Aliás, o x = ""
nesse caso significa que todas as observações estarão no mesmo ponto do eixo x, porque todos terão o valor ""
definindo a posição no eixo x. É um truque se você quer ver o boxplot de tudo.
Mas os problemas:
E na estética também. Caso você não esteja acostumado, .1 = 0.1
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = "star wars", y = height)) +
geom_boxplot(width = .1)
Sobrepor todos os pontos no boxplot com geom_jitter
ou ggbeeswarm::geom_quasirandom
dá os detalhes junto com sumário que é o boxplot. Nesse caso, é importante omitir os pontos plotados pelo boxplot, para não repetÃ-los. Também ajuda mudar a cor e transparência dos pontos.
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = "", y = height)) +
geom_boxplot(width = .2, outlier.colour = NA) +
geom_jitter(
width = .05,
alpha = .4,
size = 1,
color = "brown"
)
Já sobre os bigodes to boxplot, temos duas opções além de usar o default: removê-los ou fazê-los indicar algo mais claro (e indicar isso junto com o gráfico!).
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = "", y = height)) +
geom_boxplot(width = .2, outlier.colour = NA, coef = 0) +
geom_jitter(
width = .05,
alpha = .4,
size = 1,
color = "brown"
) +
labs(
x = "Personagens",
y = "Altura (cm)",
title = "Sem as linhas"
)
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = "", y = height)) +
geom_boxplot(width = .2, outlier.colour = NA, coef = 1000) +
geom_jitter(
width = .05,
alpha = .4,
size = 1,
color = "brown"
) +
labs(
x = "Personagens",
y = "Altura (cm)",
title = "As linhas indo ao máximo e mÃnimo"
)
Nessa segunda opção, coef
é o coeficiente que determina a quantas vezes o IQR no máximo a linha vai. Colocando um valor muito alto, ela irá até valores (ex: 1000*IQR) muito altos e baixos, e incluirá o máx e min.
As mesmas dicas valem para comparar vários boxplots:
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = species_short, y = height)) +
geom_boxplot(width = .2)
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = species_short, y = height)) +
geom_boxplot(width = .2, outlier.colour = NA, coef = 1000) +
geom_jitter(width = 0.05, alpha = 0.4, color = "orange")
Quando o eixo x é um número, precisamos indicar ao boxplot que dados vão em cada caixa:
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = n_films, y = height, group = n_films)) +
geom_boxplot(width = .2,
outlier.colour = NA,
coef = 1000) +
geom_jitter(width = 0.05,
alpha = 0.4,
color = "orange")
Caso queiramos criar nossos grupos, a função cut
ajuda:
starwars %>%
filter(!is.na(height)) %>%
mutate(n_filmes_g = cut(n_films, breaks = c(0, 3, 5, 10))) %>%
ggplot(aes(x = n_filmes_g, y = height, group = n_filmes_g)) +
geom_boxplot(width = .2,
outlier.colour = NA,
coef = 1000) +
geom_jitter(width = 0.05,
alpha = 0.4,
color = "orange")
Outra opção legal é colocar o boxplot ao lado dos pontos:
starwars %>%
filter(!is.na(height)) %>%
ggplot(aes(x = species_short, y = height)) +
geom_boxplot(
width = .2,
outlier.colour = NA,
coef = 1000,
position = position_nudge(.2),
color = "grey"
) +
geom_jitter(width = .05,
height = 0,
alpha = 0.4)