ggblanket

David Hodge

Overview

ggblanket is a package of ggplot2 wrapper functions.

The primary objective is to simplify ggplot2 visualisation.

Secondary objectives relate to:

Computational speed has been traded-off.

How it works

  1. First setup with set_blanket()
  2. Each gg_* function wraps a geom
  3. A merged col argument to colour/fill by a variable
  4. A facet argument to facet by a variable
  5. A facet2 argument to facet by a 2nd variable
  6. Other aesthetics via mapping argument
  7. Prefixed arguments to customise x/y/col/facet
  8. Smart *_label defaults for axis and legend titles
  9. Other ggplot2::geom_* arguments via ...
  10. Families of *_mode_* themes with legend variants
  11. Helpful orientation defaults and side-effects
  12. Ability to add multiple geom_* layers
  13. Arguments to customise setup with set_blanket()
  14. A gg_blanket() function with geom flexibility
library(dplyr)
library(stringr)
library(ggplot2)
library(scales)
library(ggblanket)
library(palmerpenguins)
library(patchwork)

penguins2 <- penguins |> 
  labelled::set_variable_labels(
    bill_length_mm = "Bill length (mm)",
    bill_depth_mm = "Bill depth (mm)",
    flipper_length_mm = "Flipper length (mm)",
    body_mass_g = "Body mass (g)",
  ) |> 
  mutate(sex = factor(sex, labels = c("Female", "Male"))) |> 
  tidyr::drop_na(sex) 

1. First setup with set_blanket()

The set_blanket() function should be run first.

This sets the default style of plots with themes and colours etc. It can be customised.

It should be run at the start of every script or quarto document.

set_blanket()

2. Each gg_* function wraps a geom

Each gg_* function wraps a ggplot2::ggplot() function with the associated ggplot2::geom_*() function.

Almost every geom in ggplot2 is wrapped.

Position related aesthetics can be added directly as arguments.

penguins2 |>
  gg_point(
    x = flipper_length_mm,
    y = body_mass_g,
  )

3. A merged col argument to colour/fill by a variable

The colour and fill aesthetics of ggplot2 are merged into a single concept represented by the col argument.

This combined aesthetic means that all colour outlines and all fill interiors should be coloured with the col_palette by the col variable.

Use colour = NA or fill = NA to turn one of these off.

penguins2 |>
  gg_boxplot(
    x = flipper_length_mm,
    y = island,
    col = sex, 
  )

4. A facet argument to facet by a variable

Users provide an unquoted facet variable to facet by.

When facet is specified, the facet_layout will default to a "wrap" of the facet variable (if facet2 = NULL).

penguins2 |>
  gg_histogram(
    x = flipper_length_mm,
    facet = species,
  )

5. A facet2 argument to facet by a 2nd variable

Users can also provide an unquoted facet2 variable to facet by.

When facet2 is specified, the facet_layout will default to a "grid" of the facet variable (horizontally) by the facet2 variable (vertically).

penguins2 |>
  gg_histogram(
    x = flipper_length_mm,
    facet = species,
    facet2 = sex,
  )

6. Other aesthetics via mapping argument

Some aesthetics are not available via an argument (e.g. alpha, size, shape, linetype and linewidth).

These can be accessed via the mapping argument using the aes() function.

To customise associated scales/guides, + on the applicable ggplot2 layer. In some situations, you may have to reverse the values in the relevant scale etc.

Note you can use set_blanket(geom_colour = lightness[1], ...) to make legend symbols black if needed.

penguins2 |> 
  gg_jitter(
    x = species, 
    y = flipper_length_mm, 
    col = island,
    mapping = aes(shape = island),
  ) 

7. Prefixed arguments to customise x/y/col/facet

There are numerous arguments to customise plots that are prefixed by whether they relate to x, y, col or facet.

For x, y and col, these relate to associated arguments within ggplot2 scales and guides. For facet, they relate to associated arguments within ggplot2::facet_wrap and ggplot2::facet_grid.

Scales and guides associated with other other aesthetics can be customised by adding the applicable ggplot2 layer.

penguins2 |>
  gg_jitter(
    x = flipper_length_mm,
    y = body_mass_g,
    col = flipper_length_mm,
    x_breaks = scales::breaks_extended(n = 4, only.loose = TRUE),
    x_labels = \(x) stringr::str_sub(x, 1, 1),
    y_expand_limits = 1000,
    y_labels = label_number(big.mark = " "), 
    y_transform = "log10",
    col_label = "Flipper\nlength (mm)",
    col_steps = TRUE,
    col_breaks = \(x) quantile(x, seq(0, 1, 0.25)),
    col_palette = viridis::rocket(n = 9, direction = -1),
  )

8. Smart *_label defaults for axis and legend titles

The x_label, y_label and col_label for the axis and legend titles can be manually specified with the applicable *_label argument (or + ggplot2::labs(...)).

If not specified, they will first take any label attribute associated with the applicable variable.

If none, they will then convert the variable name to a label name using the label_to_case function, which defaults to sentence case (i.e. snakecase::to_sentence_case).

penguins2 |>
  gg_freqpoly(
    x = flipper_length_mm,
    col = species,
  )

9. Other ggplot2::geom_* arguments via ...

The ... argument provides access to all other arguments in the ggplot2::geom_*() function.

Common arguments to add include colour, fill, alpha, linewidth, linetype, size and width, which enables fixing of these to a particular value.

Use the ggplot2::geom_* help to see what arguments are available.

penguins2 |>
  gg_smooth(
    x = flipper_length_mm,
    y = body_mass_g,
    col = sex, 
    col_palette = c("#003f5c", "#ffa600"),
    colour = "#bc5090", 
    linewidth = 1, 
    linetype = "dashed",
    alpha = 1, 
    se = TRUE, 
    level = 0.999, 
  ) 

10. Families of *_mode_* themes with legend variants

light_mode_*, grey_mode_* and dark_mode_* theme families are provided with variants that differ based on legend placement with suffix r (right), b (bottom), t (top) and n (none).

These themes were built for use with the mode argument.

penguins2 |>
  gg_histogram(
    x = flipper_length_mm,
    col = species,
    title = "Penguin flipper length by species",
    subtitle = "Palmer Archipelago, Antarctica",
    caption = "Source: Gorman, 2020", 
    mode = grey_mode_t() + theme(legend.title = element_blank()),
  ) 

11. Helpful orientation defaults and side-effects

If not specified, the gg_* function will guess the plot orientation (based on whether the y axis is discrete).

Where x_orientation = TRUE, it will:

The vice versa will occur for when y_orientation = TRUE.

Note you can avoid all this by +-ing your theme on to the gg_* output, and adding a *_limits = c(NA, NA) argument (or *_limits = c(0, NA) for bars).

p1 <- penguins2 |>
  gg_jitter(
    x = sex,
    y = bill_depth_mm,
    subtitle = "\nx_orientation = TRUE",
  )

p2 <- penguins2 |>
  gg_jitter(
    x = bill_depth_mm,
    y = sex,
    subtitle = "\ny_orientation = TRUE",
  ) 

p1 + p2

12. Ability to add multiple geom_* layers

Users can make plots with multiple layers by adding on ggplot2::geom_* layers.

Aesthetics directly added in the gg_* function are globally inherited. Those added via the mapping argument are only available locally to the layer associated with the gg_* function.

It works best to add as many of the globally inherited aesthetics as possible to the gg_* function.

The gg_*() function should also be appropriate to be the bottom layer of the plot. You may sometimes need to use gg_blanket() which defaults to a blank geom.

penguins2 |>
  group_by(species, sex) |>
  summarise(
    lower = quantile(flipper_length_mm, probs = 0.05),
    upper = quantile(flipper_length_mm, probs = 0.95),
    flipper_length_mm = mean(flipper_length_mm, na.rm = TRUE),
  ) |>
  labelled::copy_labels_from(penguins2) |>
  gg_col(
    x = flipper_length_mm,
    xmin = lower, 
    xmax = upper,
    y = species,
    col = sex,
    position = position_dodge(),
    width = 0.75,
  ) +
  geom_errorbar(
    width = 0.1, 
    position = position_dodge(width = 0.75),
    colour = lightness[1],
  )  

13. Arguments to customise setup with set_blanket()

The set_blanket function sets customisable defaults for the:

The ggplot2::update_geom_defaults() function can be used to further fine-tune geom defaults.

set_blanket() also works on ggplot2 code.

set_blanket(
  mode = dark_mode_r(), 
  geom_colour = "#e7298a",
  annotate_colour = darkness[1],
  col_palette_d = c("#1b9e77", "#d95f02", "#7570b3", "#e7298a", "#66a61e", 
                    "#e6ab02", "#a6761d", "#666666"), #RColorBrewer Dark2 
)

p1 <- penguins2 |>
  gg_point(
    x = flipper_length_mm, 
    y = body_mass_g,
    x_breaks = breaks_extended(n = 4, only.loose = TRUE),
  ) +
  geom_vline(xintercept = 200) +
  annotate("text", x = I(0.25), y = I(0.75), label = "Here")

p2 <- penguins2 |> 
  gg_histogram(
    x = flipper_length_mm,
    col = species,
    x_breaks = breaks_extended(n = 4, only.loose = TRUE),
  ) +
  geom_vline(xintercept = 200) +
  annotate("text", x = I(0.75), y = I(0.75), label = "Here")

p1 + p2


set_blanket()

14. A gg_blanket() function with geom flexibility

The package is driven by the gg_blanket function, which has a geom argument with ggplot2::geom_blank defaults for geom, stat and position.

All other functions wrap this function with a fixed geom, and their own default stat and position arguments as per the applicable geom_* function.

This function can often be used with geoms that do not have an associated gg_* function.

geom_spoke()
#> geom_spoke: na.rm = FALSE
#> stat_identity: na.rm = FALSE
#> position_identity

expand.grid(x = 1:10, y = 1:10) |>
  tibble() |>
  mutate(angle = runif(100, 0, 2*pi)) |>
  mutate(speed = runif(100, 0, sqrt(0.1 * x))) |>
  gg_blanket(
    geom = "spoke",
    x = x, 
    y = y,
    col = speed,
    mapping = aes(angle = angle, radius = speed),
  ) +
  geom_point()

Further information

See the ggblanket website for further information, including articles and function reference.