Who am I?

Data visualisation specialist, mainly working with R, Python, and D3.js.


Background in statistics, operational research, and data science consultancy.


Co-author of Royal Statistical Society’s Best Practices for Data Visualisation guidance.


Author of The Art of Data Visualization with ggplot2.


Hex logos

Brief refresher of ggplot2 basics

  • ggplot() (data and mapping)
  • aes()
  • geom_*()
  • scales()
  • theme()

ggplot2 hex logo

What are some common ggplot2 issues?

Bluesky screenshot

What are some common ggplot2 issues?

  • Sizing and scaling (especially text)
  • Fonts
  • Placing annotations
  • Remembering all of the theme options
  • Legends

What are some common ggplot2 issues?

Bluesky screenshot

Some small ggplot2 changes

  • plot saving and sizing
  • text sizing
  • overlapping facet labels
  • axis labels

Before we go any further!

Have you ever spent ages tinkering with a plot you’re previewing in RStudio…

Stacked bar chart

Before we go any further!

…and then used ggsave() to save an image, and ended up with something like this:

Stacked bar chart not looking very nice

Why does this happen?

  • This happens because we preview the chart at 96dpi (low resolution) in RStudio, but save the chart at 300dpi (high resolution) using the defaults for ggsave().

  • We could set ggsave(dpi = 96) but we usually don’t want to save a low resolution image.

  • Instead we want to preview the chart in RStudio at the higher resolution we’ll be saving it at.

How do we fix this?

ggview: github.com/idmn/ggview

  • Preview the ggplot2 output directly with your specifications in RStudio IDE - you’ll get what you see

ggview hex sticker

Dealing with text

Some common problems:

  • theme text
    • Many elements of to set the text size of
    • Resizing chart means redefining text sizes
  • geom text
    • Scales differently from theme sizes
  • axis text
    • Long (ugly labels)
    • Overlapping labels

Exercise 1

  • Change to using facets instead of (or as well as) colours.
  • Make sure the year labels can all be read.
  • Make sure it saves nicely with a width of 6 inches and a height of 4 inches.
  • Increase all font sizes to be larger.
  • Add a title, and further increase the size of the title text.
ggplot(
  data = plot_data,
  mapping = aes(x = year, y = value, colour = country_name)
) +
  geom_line()

ggplot2 extensions

Screenshot of extensions gallery

Dealing with loooooooooooooooooooong text

Chart with truncated subtitle

Chart with truncated subtitle

Dealing with loooooooooooooooooooong text

Manual solutions

  • Adding line breaks with \n directly to the text string
  • Using str_wrap() to add line breaks and set the number of characters per line

Automated solutions

  • ggtext
  • marquee

Annotations in R

There are many packages for working with annotations in ggplot2:

  • ggplot2
  • ggtext
  • cowplot
  • ggannotate
  • ggrepel
  • …

Placing annotations

  • Where should the annotation go? -> ggannotate
  • Single facet annotations -> ggh4x
  • Wrap long annotation text -> ggtext
  • Annotations outside panel -> cowplot
  • Many overlapping annotations -> ggrepel

Tip: use glue to create data-driven annotations

Exercise 2

  • Use either ggtext or marquee to ensure the subtitle text wraps onto multiple lines.
  • Use either ggtext or marquee to make sure country names are all visible in the facet labels.
  • Add an annotation to the "Australia" facet.

Use variables

Create variable for colours:

text_col <- "grey10"
highlight_col <- "#B01D5F"
bg_col <- "white"

Custom themes

Remembering all of the theme elements is tricky

  • Step 1: Parameterise your theme elements
  • Step 2: Make your own reusable function by adapting an existing theme
  • Step 3: Put your function in a package (optional)
  • Step 4: Set up reusable templates for new ggplot2 charts (optional)

Template files

Create a template file (inside or outside of a package) that contains the theme() defaults you want to use.

# Load packages -----------------------------------------------------------

library(tidyverse)
library(showtext)
library(ggtext)
library(glue)
library(ggview)


# Load data ---------------------------------------------------------------



# Load fonts --------------------------------------------------------------

font_add_google("Oswald")
font_add_google("Nunito")
showtext_auto()
showtext_opts(dpi = 300)
title_font <- "Oswald"
body_font <- "Nunito"


# Define colours and fonts-------------------------------------------------

bg_col <- "#F2F4F8"
text_col <- "#151C28"
highlight_col <- "#7F055F"


# Data wrangling ----------------------------------------------------------


# Define text -------------------------------------------------------------

title <- ""
st <- ""
cap <- ""


# Plot --------------------------------------------------------------------

theme_minimal(base_size = 10, base_family = body_font) +
  theme(
    plot.margin = margin(5, 5, 5, 5),
    plot.title.position = "plot",
    plot.caption.position = "plot",
    plot.background = element_rect(fill = bg_col, colour = bg_col),
    panel.background = element_rect(fill = bg_col, colour = bg_col),
    plot.title = element_textbox_simple(
      colour = text_col,
      hjust = 0,
      halign = 0,
      margin = margin(b = 5, t = 5),
      family = title_font,
      face = "bold",
      size = rel(1.5)
    ),
    plot.subtitle = element_textbox_simple(
      colour = text_col,
      hjust = 0,
      halign = 0,
      margin = margin(b = 5, t = 5),
      family = body_font
    ),
    plot.caption = element_textbox_simple(
      colour = text_col,
      hjust = 0,
      halign = 0,
      margin = margin(b = 0, t = 10),
      family = body_font
    ),
    strip.text = element_textbox_simple(
      face = "bold",
      margin = margin(t = 10),
      size = rel(0.9)
    ),
    panel.grid.minor = element_blank()
  ) +
  canvas(
    width = 7, height = 5,
    units = "in", bg = bg_col,
    dpi = 300
  ) # -> p


# Save --------------------------------------------------------------------

save_ggplot(
  plot = p,
  file = "image.png"
)

Exercise 3

  • Creating your own theme() function
    • Use ggtext and marquee to auto-wrap text
    • Set facet height
    • Apply desired styling

Resources

Resources logo