Data visualization – exercise solutions

Day 4, C

Author

Michael C Sachs

Create your own theme

Load the ggplot2 package and customize your own theme. Look at the built-in themes and the ggthemes package for inspiration.

Tips

  1. You can save your customization using the theme(), but that will only modify the current theme
library(ggplot2)
library(palmerpenguins)

mytheme <- theme(strip.background = element_rect(fill = "steelblue"), 
        text = element_text(family = "Comic sans"), 
        plot.background = element_rect(fill = "grey81"), 
        legend.background = element_rect(fill = NA), 
        legend.position = "bottom"
        ) 

ggplot(penguins, aes(x = body_mass_g, y = bill_length_mm, color = species)) + 
  geom_point() + facet_wrap(~ year) + mytheme
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

theme_set(theme_bw())
ggplot(penguins, aes(x = body_mass_g, y = bill_length_mm, color = species)) + 
  geom_point() + facet_wrap(~ year) + mytheme
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

  1. To make a fully custom theme, start with an existing one, and modify it
my_fulltheme <- theme_grey() + mytheme

ggplot(penguins, aes(x = body_mass_g, y = bill_length_mm, color = species)) + 
  geom_point() + facet_wrap(~ year) + my_fulltheme
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

  1. Save your favorite color scales as a function for easy reuse. Use discrete_scale or continuous_scale.
my_qual_scale <- function(...) {
  discrete_scale("color", scale_name = "OI", 
                 palette = function(x) {
                   res <- palette.colors(x, "Okabe-Ito")[1:x]
                   names(res) <- NULL
                   res
                 }, ...)
}

ggplot(penguins, aes(x = body_mass_g, y = bill_length_mm, color = species)) + 
  geom_point() + facet_wrap(~ year) + my_fulltheme + my_qual_scale()
Warning: The `scale_name` argument of `discrete_scale()` is deprecated as of ggplot2
3.5.0.
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

Complex figures with base graphics

Check out this violin plot

ggplot(penguins, aes(x = species, y = body_mass_g)) + geom_violin() + geom_jitter()
Warning: Removed 2 rows containing non-finite outside the scale range
(`stat_ydensity()`).
Warning: Removed 2 rows containing missing values or values outside the scale range
(`geom_point()`).

How would you produce a similar plot using base graphics? After doing so, reflect, do you appreciate to convenience and flexibility of ggplot2?

Use the density function to calculate the densities by species. The results are stored in a list with elements x and y. Then transform by rotating 90 degrees and mirroring. Plot the result using the polygon function.

dens_by_species <- split(penguins$body_mass_g, penguins$species) |> 
  lapply(density, na.rm = TRUE, cut = 0)

plot(body_mass_g ~ jitter(as.numeric(as.factor(species))), 
     data = penguins, xaxt = "n", xlab = "species")

for(i in 1:length(dens_by_species)) {
  
  den <- dens_by_species[[i]]
  newx <- c(0.2 * (den$y / max(den$y)) + i, 
            rev(-0.2 * (den$y / max(den$y)) + i))
  newy <- c(den$x, rev(den$x))
  
  polygon(newx,  newy)
}
axis(side = 1, at = 1:3, labels = levels(as.factor(penguins$species)))