Plotting data

ggplot, part 2

Roland Krause

MADS6

Tuesday, 12 November 2024

Introduction

More ggplot2!

Scales catalogue

Scales for all

Scaling vs mapping

Mapping is the function for associating a data column with an aesthetic.

Scales are the functions that associate a data value with a visual point.

Functions are based on this scheme:

scale_{aes}_{type}()

Arguments to change default

  • breaks, choose where are labels
  • labels, usually with package scales
  • trans, to change to i.e log

62 functions available!

Scales package

scales::label_percent()(c(0.4, 0.6, .95))
[1] "40%" "60%" "95%"
scales::label_comma()(20^(1:4))
[1] "20"      "400"     "8,000"   "160,000"
scales::breaks_log()(20^(1:3))
[1]    10    30   100   300  1000  3000 10000

Starwars characters

ggplot(starwars, 
       aes(x = height, y = mass)) +
  geom_point(size = 2)

Starwars characters: log-transform

ggplot(starwars, 
       aes(x = height, y = mass)) +
  geom_point(alpha = 0.6, size = 2) +
  scale_y_continuous(trans = "pseudo_log") 

Starwars characters: who is the massive guy?

ggplot(starwars, 
       aes(x = height, y = mass)) +
  geom_point(alpha = 0.6, size = 2) +
  scale_y_continuous(trans = "pseudo_log") +
  geom_text(data = \(x) filter(x, mass > 1000),
            aes(label = name), nudge_y = -0.2) 

Tip

All geometries geom_ can take either a data.frame or a function, here geom_text().

Colors

Custom colors

Better: see Emil Hvitfeldt repo

Changing colours for categories

Default is scale_fill_hue()

filter(starwars, !is.na(gender)) |>
ggplot(aes(y = gender,
          fill = fct_lump_n(species, 8) |>
                 fct_infreq())) +
  geom_bar(position = "fill") +
  scale_fill_hue() +
  labs(fill = "Top 8 Species\n(ranked)")

Brewer is a safe alternative

filter(starwars, !is.na(gender)) |>
ggplot(aes(y = gender,
          fill = fct_lump_n(species, 8) |>
                 fct_infreq())) +
  geom_bar(position = "fill") +
  scale_fill_brewer(palette = "Set1") +
  labs(fill = "Top 8 Species\n(ranked)")

Predefined colour palettes

library(RColorBrewer)
par(mar = c(0, 4, 
            0, 0))
display.brewer.all()

Applying a palette

Colour gradient, for continuous variables

Default gradient

penguins |>
  ggplot(aes(x = bill_length_mm, 
             y = bill_depth_mm, 
             colour = body_mass_g)) +
  geom_point(alpha = 0.6, size = 5)

Viridis gradient

penguins |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm, 
             colour = body_mass_g)) +
  geom_point(alpha = 0.6, size = 5) +
  scale_color_viridis_c()

Viridis gradient is usually an improvement

Default ggplot2 is prints(!) well but on screens better off using viridis.

scale_color_viridis_c() c for continuous.

Viridis palettes

  • 5 different scales
  • Also for discrete variables
  • viridis is colour blind friendly and nice in b&w
  • In ggplot2 since v3.0 but no the default
penguins |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm, 
             colour = species)) +
  geom_point(alpha = 0.6, size = 5) +
  scale_color_viridis_d()

Binning instead of gradient

Binning help grouping observations

  • Default blue gradient, viridis option
  • Number of bins, limits can be changed
penguins |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm, 
             colour = body_mass_g)) +
  geom_point(alpha = 0.6, size = 5) +
  scale_color_binned(type = "viridis")

Merge similar guides

Size & colour on same variable ➡️ 2 guides

penguins |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm, 
             colour = body_mass_g,
             size = body_mass_g)) +
  geom_point(alpha = 0.6) +
  scale_color_viridis_c()

guides() merge both aesthetics

penguins |>
  ggplot(aes(x = bill_length_mm, y = bill_depth_mm, 
             colour = body_mass_g, size = body_mass_g)) +
  geom_point(alpha = 0.6) +
  scale_color_viridis_c() +
  guides(colour = "legend")

Labels and themes

How to set the title

Default: column name

ggplot(penguins, 
       aes(bill_depth_mm, 
           bill_length_mm)) + 
  geom_point()

Labels - labs()

ggplot(penguins, aes(bill_depth_mm, bill_length_mm)) + 
  geom_point() +
  labs(x = "Bill depth (mm)",
       y = "Bill length (mm)")

Appearance - theme()

ggplot(penguins, aes(bill_depth_mm, bill_length_mm)) + geom_point() +
    labs(x = "Bill depth (mm)", y = "Bill length (mm)") +
  theme(axis.title = 
          element_text(colour ="red"))

Labels and guides

Setting legends

Default: column name

ggplot(penguins, 
       aes(bill_depth_mm, 
           bill_length_mm, 
           colour = species)) + 
  geom_point()

Labels - labs()

ggplot(penguins, aes(bill_depth_mm, bill_length_mm, colour = species)) + 
  geom_point() +
  labs(x = "Bill depth (mm)",
       y = "Bill length (mm)",
       colour = "Guide for\npenguins") 

Appearance - guides()

ggplot(penguins, aes(bill_depth_mm, bill_length_mm, colour = species)) + geom_point() +
    labs(x = "Bill depth (mm)", y = "Bill length (mm)") +
  guides(colour =
    guide_legend(title = "My penguin\nguide",
                 reverse = TRUE)) 

Facets

Facets: facet_wrap()

Creating facets

  • Easiest way: facet_wrap()
  • Use the vars() function
  • or a formula (in R ~)
ggplot(penguins, 
       aes(bill_depth_mm, 
           bill_length_mm)) +
  geom_point() +
  facet_wrap(vars(species))

Facets layout

Specify the number of rows/columns:

  • ncol = integer
  • nrow = integer
fc <- ggplot(penguins, 
       aes(bill_depth_mm, 
           bill_length_mm)) +
  geom_point()
fc + facet_wrap(vars(species), ncol = 2)

Facets, free scales

⚠️ Make comparison harder

  • x or y (free_x / free_y)
fc + facet_wrap(vars(species), scales = "free_y")

  • Both axis
fc + facet_wrap(vars(species), scales = "free")

facet_grid() to lay out panels in a grid

ggplot(penguins, 
       aes(bill_depth_mm, 
           bill_length_mm)) +
  geom_point() +
  facet_grid(rows = vars(island), cols = vars(species))

Grid lay out

  1. Specify rows and columns
  2. Formular interface rows on the left, columns on the right separated by a tilde ~

Barplots in facets

facet_grid() can also be used with one variable, complemented by a placeholder: .

Waste of space

ggplot(starwars) +
  geom_bar(aes(y = gender, fill = sex)) +
  facet_grid(fct_lump_min(species, 4) ~ .) +
  labs(y = NULL)

Optimize by removing empty slots

ggplot(starwars) +
  geom_bar(aes(y = gender, fill = sex)) +
  facet_grid(fct_lump_min(species, 4) ~ .,
             space = "free", scales = "free_y") +
  labs(y = NULL)

Extensions

Extending ggplot2

Finding working extensions

ggplot2 introduced the possibility for the community to create extensions, they are referenced on a dedicated site

Black theme

Using Bob Rudis hrbrthemes package

library(hrbrthemes)
ggplot(penguins,
       aes(x = bill_length_mm,
           y = bill_depth_mm,
           colour = species)) +
  geom_point() +
  geom_smooth(method = "lm", formula = 'y ~ x',
      # no standard error ribbon
              se = FALSE) +
  facet_grid(island ~ .) +
  labs(x = "length (mm)", y = "depth (mm)",
       title = "Palmer penguins",
       subtitle = "bill dimensions over location and species",
       caption = "source: Horst AM, Hill AP, Gorman KB (2020)") +
  # hrbrthemes specifications
  scale_fill_ipsum() +
  theme_ft_rc(14) +
  # tweak the theme
  theme(panel.grid.major.y = element_blank(),
   panel.grid.major.x = element_line(size = 0.5),
   plot.caption = element_text(face = "italic"),
   strip.text = element_text(face = "bold"),
   plot.caption.position = "plot")

Compose plots with patchwork

Create three plots and give them names

p1 <- ggplot(penguins, 
             aes(x = species)) +
  geom_bar() +
  labs(title = "Species distribution")
p2 <- ggplot(penguins, 
             aes(y = island)) +
  geom_bar() +
  labs(title = "Island but flipped")
p3 <- ggplot(penguins, 
             aes(x = body_mass_g,
                 y = bill_depth_mm,
                 colour = sex)) +
  geom_point()
p1

p2

Now, compose them!

p3

Compose plots with patchwork

library(patchwork)
(( p1 | p2 ) / p3) +
  # add tags and main title
  plot_annotation(tag_levels = 'A',
                  title = 'Plots about penguins') &
  # modify all plots recursively
  theme_minimal() +
  theme(text = element_text('Roboto'))

Composition

patchwork provides an API using the classic arithmetic operators

Polished example by Cédric Scherer

Using patchwork, ggforce T. Pedersen and ggtext Claus O. Wilke

Text paths, curved labels in data

library(geomtextpath)
ggplot(penguins,
       aes(x = bill_length_mm, y = bill_depth_mm, colour = species)) +
  geom_point(alpha = 0.3) +
  stat_ellipse(aes(label = species),
    geom = "textpath", hjust = c(0.55)) +
  theme_bw(14) + guides(color = "none")

ggplot(penguins,
       aes(x = bill_length_mm / bill_depth_mm, 
           colour = species)) +
  stat_density(aes(label = species),
    geom = "textpath", hjust = c(0.25)) +
  theme_bw(14) + guides(color = "none")

Exporting, interactive or passive mode

Right panel

  • Using the Export button in the Plots panel

ggsave

  • Save the ggplot object, 2nd argument, here p or last_plot()
  • Guesses the output type by the extension (svg, png, svg, etc.)
ggsave("my_name.png", p, width = 60, height = 30, units = "mm")
ggsave("my_name.pdf", last_plot(), width = 50, height = 50, units = "mm")

Quarto documents

  • If needed, adjust the chunk options:
    • Size: fig-height, fig-width
    • Ratio: fig-asp

Missing features

Geoms list here

  • geom_tile() heatmap
  • geom_bind2d() 2D binning
  • geom_abline() slope

Stats list here

  • stat_ellipse() (ggforge seen)
  • stat_summary() easy mean, 95CI etc.

Plot on multi-pages

  • ggforce::facet_grid_paginate() facets
  • gridExtra::marrangeGrob() plots

Coordinate / transform

  • coord_cartesian() for zooming in

Customise theme elements

  • Legend & guide tweaks
  • Major/minor grids
  • Font, faces
  • Margins
  • Labels & ticks
  • Strip positions
  • See live examples of pre-built themes

Build your plot with point and click

Using esquisse Rstudio addin by dreamRs

Before we stop

You learned to:

  • Apprehend facets
  • Color schemes and gradients
  • Discover extensions
  • The endless potential of cosmetic improvements

Further reading

Thank you for your attention!

*: Palmer penguins, data are available by CC-0 license and Artwork by Allison Horst