Figure design

Claus O. Wilke

2024-12-28

How do we go from this

 

   to this?

 

Requires coordinated modification of multiple elements:

  • geoms (via arguments to geoms)
  • scales (via scale_*() functions)
  • plot appearance (via themes)

The starting point, a rough draft

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges()

 

You can download the dataset using this code:

lincoln_temps <- readRDS(url("https://wilkelab.org/SDS366/datasets/lincoln_temps.rds"))

Set scale and bandwidth to shape ridgelines

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4
  )

 

Set rel_min_height to cut ridgelines near zero

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01
  )

 

Use scale_*() functions to specify axis labels

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01,
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)"
  ) +
  scale_y_discrete(
    name = NULL  # NULL means no label
  )

 

Specify scale expansion

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)",
    expand = c(0, 0)
  ) +
  scale_y_discrete(
    name = NULL,
    expand = expansion(add = c(0.2, 2.6))
  )

 

Set overall plot theme

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)",
    expand = c(0, 0)
  ) +
  scale_y_discrete(
    name = NULL,
    expand = expansion(add = c(0.2, 2.6))
  ) +
  theme_minimal_grid()  # from cowplot

 

Align y axis labels to grid lines

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)",
    expand = c(0, 0)
  ) +
  scale_y_discrete(
    name = NULL,
    expand = expansion(add = c(0.2, 2.6))
  ) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(vjust = 0)
  )

 

Change fill color from default gray to blue

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01,
    fill = "#7DCCFF"
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)",
    expand = c(0, 0)
  ) +
  scale_y_discrete(
    name = NULL,
    expand = expansion(add = c(0.2, 2.6))
  ) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(vjust = 0)
  )

 

Draw lines in white instead of black

ggplot(lincoln_temps) +
  aes(x = mean_temp, y = month_long) +
  geom_density_ridges(
    scale = 3, bandwidth = 3.4,
    rel_min_height = 0.01,
    fill = "#7DCCFF",
    color = "white"
  ) +
  scale_x_continuous(
    name = "mean temperature (°F)",
    expand = c(0, 0)
  ) +
  scale_y_discrete(
    name = NULL,
    expand = expansion(add = c(0.2, 2.6))
  ) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(vjust = 0)
  )

 

Working with ggplot themes

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point()
  # default theme is theme_gray()

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_gray()

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_gray(14) # most themes take a font-size argument to scale text size

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_bw(14)

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_minimal(14)

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_classic(14)

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_half_open()  # from package cowplot

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_minimal_grid()  # from package cowplot

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_minimal_hgrid()  # from package cowplot

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_minimal_vgrid()  # from package cowplot

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_economist(14)       # from package ggthemes

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_economist(14) + # from package ggthemes
  scale_color_economist() 

 

Using ready-made themes

ggplot(penguins, aes(flipper_length_mm, body_mass_g, color = species)) +
  geom_point() +
  theme_fivethirtyeight(14) + # from package ggthemes
  scale_color_fivethirtyeight()

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid()

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # change overall font family
    # (requires font to be available)
    text = element_text(
      family = "Comic Sans MS"
    )
  )

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # change color of axis titles
    axis.title = element_text(
      color = "royalblue2"
    )
  )

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # change color of only the x axis title
    axis.title.x = element_text(
      color = "royalblue2"
    )
  )

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # change all text colors?
    # why does it not work?
    text = element_text(color = "royalblue2")
  )

 

Customizing theme elements

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    text = element_text(color = "royalblue2"),
    axis.text = element_text(
      color = "royalblue2"
    )
  )

 

The element axis.text has its own color set in the theme. Therefore it doesn’t inherit from text.

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.title.x = element_text(
      # horizontal justification
      # (0 = left)
      hjust = 0
    )
  )

 

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.title.x = element_text(
      # horizontal justification
      # (0.5 = center)
      hjust = 0.5
    )
  )

 

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.title.x = element_text(
      # horizontal justification
      # (1 = right)
      hjust = 1
    )
  )

 

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(
      # vertical justification
      # (0 = bottom)
      vjust = 0
    )
  )

 

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(
      # vertical justification
      # (0.5 = center)
      vjust = 0.5
    )
  )

 

Horizontal and vertical alignment

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    axis.text.y = element_text(
      # vertical justification
      # (1 = top)
      vjust = 1
    )
  )

 

Remove elements entirely: element_blank()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # all text gone
    text = element_blank()
  )

 

Remove elements entirely: element_blank()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    # no axis titles
    axis.title = element_blank()
  )

 

Set background color: element_rect()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    plot.background = element_rect(
      fill = "aliceblue"
    )
  )

 

Set background color: element_rect()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    panel.background = element_rect(
      fill = "aliceblue"
    )
  )

 

Set background color: element_rect()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    legend.box.background = element_rect(
      fill = "aliceblue",
      color = "steelblue4" # line color
    )
  )

 

Set background color: element_rect()

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    legend.box.background = element_rect(
      fill = "aliceblue",
      color = "steelblue4" # line color
    ),
    legend.box.margin = margin(7, 7, 7, 7)
  )

 

Move the legend: legend.position

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    legend.box.background = element_rect(
      fill = "aliceblue",
      color = "steelblue4" # line color
    ),
    legend.box.margin = margin(7, 7, 7, 7),
    # legend on top of plot
    legend.position = "top"
  )

 

Move the legend: legend.position

ggplot(penguins) +
  aes(flipper_length_mm, body_mass_g) +
  geom_point(aes(color = species)) +
  theme_minimal_grid() +
  theme(
    legend.box.background = element_rect(
      fill = "aliceblue",
      color = "steelblue4" # line color
    ),
    legend.box.margin = margin(7, 7, 7, 7),
    # legend inside plot
    legend.position = "inside", 
    # relative position inside plot panel
    legend.position.inside = c(0.98, 0.02),
    # justification relative to position
    legend.justification = c(1, 0)
  )

 

Further reading