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 to achieve these objectives.

How it works

  1. Almost forty gg_* wrapper functions
  2. A col argument to colour and fill by a variable
  3. A facet argument to facet by a variable
  4. A facet2 argument to facet by a 2nd variable
  5. Prefixed arguments to customise x, y, col and facet properties
  6. Unspecified titles converted to snakecase::sentence_case
  7. Access to other geom_* arguments via ...
  8. A symmetrical continuous scale with easy opt-out
  9. Ability to add multiple geom_* layers
  10. Access other aesthetics via mapping
  11. A mode argument designed for provided *_mode_* themes
  12. Families of *_mode_* themes that differ by legend placement
  13. Set the mode and geom defaults with set_blanket
  14. A gg_blanket() function with geom flexibility
library(ggblanket)
library(ggplot2)
library(dplyr)
library(stringr)
library(tidyr)
library(palmerpenguins)
library(patchwork)

set_blanket()

1. Almost forty gg_* wrapper functions

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

Each gg_* function is named after the geom_* function it wraps.

Note at the start of every script, the set_blanket function should be run to set the default style for subsequent ggblanket plots.

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

2. A single col argument to colour and 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 everything should be coloured according to it, i.e. all coloured outlines and filled interiors.

penguins |>
  gg_point(
    x = flipper_length_mm,
    y = body_mass_g, 
    col = species,
  )

penguins |>
  drop_na(sex) |>
  mutate(across(sex, str_to_sentence)) |>
  gg_bar(
    position = "dodge",
    y = species, 
    col = sex,
    width = 0.75,
  )

3. A facet argument to facet by a variable

Faceting is treated as if it were an aesthetic. Users just provide an unquoted variable to facet by.

Whenever a facet variable is provided (and a facet2 variable not provided), the facet_layout will default to "wrap".

penguins |>
  drop_na(sex) |> 
  mutate(across(sex, str_to_sentence)) |> 
  gg_histogram(
    x = flipper_length_mm,
    facet = species,
  )

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

A facet2 argument is also provided for extra functionality and flexibility.

This enables users to facet easily in a "grid" layout of the facet variable horizontally by the facet2 variable vertically.

Whenever a facet2 variable is provided, the facet_layout will default to "grid".

penguins |>
  mutate(across(sex, str_to_sentence)) |> 
  gg_histogram(
    x = flipper_length_mm,
    facet = species,
    facet2 = sex,
  )

5. Prefixed arguments to customise x, y, col and facet properties

ggblanket offers numerous arguments to customise that are prefixed by whether they relate to x, y, col, facet or alpha.

These prefixed arguments work nicely with the Rstudio auto-complete, if users ensure their settings support the use of tab for auto-completions and multi-line auto-completions (i.e. Tools - Global Options - Code - Completion).

Everything prefixed col_ relates to both the colour and fill scale as applicable. Everything prefixed facet_ relates to both facet and facet2 as applicable.

penguins |>
  drop_na(sex) |>  
  gg_jitter(
    x = species,
    y = body_mass_g,
    col = flipper_length_mm,
    facet = sex,
    x_labels = \(x) str_sub(x, 1, 1),
    y_breaks = scales::breaks_width(1000),
    y_expand_limits = 2000,
    y_labels = scales::label_number(big.mark = " "), 
    y_transform = "log10",
    y_title = "Body mass (g)",
    col_steps = TRUE,
    col_breaks = \(x) quantile(x, seq(0, 1, 0.25)),
    col_pal = viridisLite::rocket(n = 9, direction = -1),
    facet_labels = str_to_sentence,
  )

6. Unspecified titles converted to snakecase::sentence_case

Unspecified x, y, col and alpha titles are converted to sentence case with snakecase::to_sentence.

However, each title can be manually changed using the applicable *_title argument. The default snakecase::to_sentence conversion can be turned off using titles_to_case = \(x) x or changed (e.g. snakecase::to_title_case).

diamonds |>
  gg_hex(
    coord = coord_cartesian(clip = "on"), 
    x = carat,
    y = price,
    y_limits = c(0, 20000),
  )

7. Access to other geom_* arguments via ...

The ... argument provides access to all other arguments in the geom_*() function. Typical arguments to add include colour, fill, alpha, linewidth, size and width.

Subsequently, for geoms that have both coloured outlines and interiors, you can turn off either of these using colour = NA/fill = NA - and/ fix one to a single colour with colour = "black"/fill = "lightgrey" etc.

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

penguins |>
  mutate(across(sex, str_to_sentence)) |> 
  drop_na(sex) |> 
  gg_smooth(
    x = flipper_length_mm,
    y = body_mass_g,
    col = sex, 
    col_pal = c("#003f5c", "#ffa600"),
    colour = "#bc5090", 
    linewidth = 1, 
    linetype = "dashed",
    alpha = 1, 
    se = TRUE, 
    level = 0.999, 
  ) 

penguins |> 
  gg_boxplot(
    y = island, 
    x = flipper_length_mm, 
    col = species,
    fill = NA,
    position = position_dodge2(preserve = "single")
  ) 

8. A symmetric continuous scale with easy opt-out

The gg_* function will generally create a symmetric continuous y scale by default with:

However, for the plots guessed to be horizontal, the vice-versa will occurs with a symmetric continuous x scale by default.

Sometimes you may need to add *_expand_limits = 0, if the lower bound of the symmetric scale falls on a number close to 0.

This symmetric continuous scale can be turned off easily using *_limits = c(NA, NA) (or *_limits = c(0, NA) for bars etc).

Note this symmetric scale does not occur where the scale has a transformation that is not "identity", "reverse", "date", "time" or "hms" - or where the other positional scale is binned.

9. Ability to add multiple geom_* layers

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

The gg_* function puts the aesthetic variables (i.e. x, y, col) within the wrapped ggplot function. Therefore, these aesthetics will inherit to any subsequent layers added.

Generally, it works bets to add all aesthetics required for the plot to the gg_* function, including the col argument.

The gg_*() function should be appropriate to be the bottom layer of the plot, as geoms are drawn in order.

This may mean that you need to use gg_blanket() as your gg_* function, as it defaults to a blank geom.

penguins |>
  group_by(species) |>
  summarise(body_mass_g = mean(body_mass_g, na.rm = TRUE)) |>
  mutate(lower = body_mass_g * 0.95) |> 
  mutate(upper = body_mass_g * 1.2) %>%
  gg_col(
    x = body_mass_g,
    xmin = lower, 
    xmax = upper,
    y = species,
    col = species,
    width = 0.75,
    x_expand_limits = c(0, max(.$upper)),
    x_labels = \(x) x / 1000, 
    x_title = "Body mass kg", 
  ) +
  geom_errorbar(
    colour = "black", 
    width = 0.1, 
  ) 

penguins |>
  group_by(species) |>
  summarise(body_mass_g = mean(body_mass_g, na.rm = TRUE)) |>
  mutate(lower = body_mass_g * 0.95) |> 
  mutate(upper = body_mass_g * 1.2) |> 
  gg_blanket( 
    x = body_mass_g,
    y = species,
    col = species,
    xmin = lower, 
    xmax = upper,
    width = 0.75,
    x_expand_limits = 0,
    x_labels = \(x) x / 1000, 
    x_title = "Body mass kg",
  ) +
  geom_col(
    colour = "#d3d3d3",
    fill = "#d3d3d3",
    alpha = 0.9,
    width = 0.75,
  ) +
  geom_errorbar(
    width = 0.1, 
  )

10. Access other aesthetics via mapping

The mapping argument provides access to other aesthetics, such as alpha, size, shape, linetype and linewidth etc.

Legend titles and element order must be aligned, if legends are to merge. Subsequently, you may need to change a title using + ggplot2::labs - or even reverse a guide.

penguins |> 
  gg_jitter(
    y = species, 
    x = flipper_length_mm, 
    col = species,
    mapping = aes(alpha = species, shape = species),
  ) +
  scale_alpha_manual(values = c(0.33, 1, 0.33)) +
  guides(alpha = guide_legend(reverse = TRUE))

11. A mode argument designed for provided *_mode_* themes

A mode argument has been designed for use with the *_mode_* themes.

With this function, the gg_* function will:

To avoid these side-effects, + the theme on to the output of gg_*.

12. Families of *_mode_* themes that differ by legend placement

Three mode families of themes are provided: light_mode_*, grey_mode_* and dark_mode_*.

Each mode family provides 4 variants that differ based on legend placement, which is represented by the suffix of the mode name of r (right), b (bottom), t (top) and n (none).

The default is light_mode_r.

These are intended for use with the mode argument.

Note: * if you want to use a quick non-bold title, use subtitle = "\n..." * a title can be removed using + labs(... = NULL) * for removing the legend title, you will often need + labs(colour = NULL, fill = NULL).

penguins |>
  gg_histogram(
    x = flipper_length_mm,
    col = species,
    title = "Penguin flipper length by species",
    subtitle = "Palmer Archipelago, Antarctica",
    caption = "Source: Gorman, 2020", 
    mode = light_mode_t(),
  ) +
  labs(colour = NULL, fill = NULL)

penguins |>
  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_b(),
  ) 

penguins |>
  gg_histogram(
    x = flipper_length_mm,
    col = species,
    title = "Penguin flipper length by species",
    subtitle = "Palmer Archipelago, Antarctica",
    caption = "Source: Gorman, 2020", 
    mode = dark_mode_r(),
  ) 

13. Set the mode and geom defaults with set_blanket

The set_blanket function is used to set the default style for ggblanket plots.

This function sets the default mode by * setting the default mode via weave_mode() * updating a series of geom defaults via weave_geom_defaults() * updating a series of geom defaults commonly used for annotation (i.e. *_vline, *_hline, *_abline, *_curve, *_text and *_label) via weave_annotate_defaults.

Within the set_blanket function, the user can select the mode, and the default geom and annotate colour.

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

set_blanket(grey_mode_r(), "#ffa600")

p1 <- penguins |>
  gg_point(
    x = flipper_length_mm, 
    y = body_mass_g,
    x_breaks = scales::breaks_pretty(3),
  ) +
  geom_vline(xintercept = 200) +
  annotate("text", x = I(0.25), y = I(0.75), label = "Here")

p2 <- penguins |> 
  gg_histogram(
    x = flipper_length_mm,
    x_breaks = scales::breaks_pretty(3),
  ) +
  geom_vline(xintercept = 200) +
  annotate("text", x = I(0.75), y = I(0.75), label = "Here")

p1 + p2

set_blanket(dark_mode_r(), "#bc5090", darkness[2])

p1 <- penguins |>
  gg_point(
    x = flipper_length_mm, 
    y = body_mass_g,
    x_breaks = scales::breaks_pretty(3),
  ) +
  geom_vline(xintercept = 200) +
  annotate("text", x = I(0.25), y = I(0.75), label = "Here")

p2 <- penguins |> 
  gg_histogram(
    x = flipper_length_mm,
    x_breaks = scales::breaks_pretty(3),
  ) +
  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

ggblanket is driven by the gg_blanket function, which has a geom argument with geom_blank defaults.

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

You can print a geom_* function to identify the applicable stat and position arguments etc.

geom_violin()
#> geom_violin: draw_quantiles = NULL, na.rm = FALSE, orientation = NA
#> stat_ydensity: trim = TRUE, scale = area, na.rm = FALSE, orientation = NA, bounds = c(-Inf, Inf)
#> position_dodge

penguins |>
  drop_na(sex) |>
  mutate(across(sex, str_to_sentence)) |>
  gg_blanket(
    geom = "violin",
    stat = "ydensity",
    position = "dodge",
    x = sex,
    y = body_mass_g,
    col = species,
  )

geom_histogram()
#> geom_bar: na.rm = FALSE, orientation = NA
#> stat_bin: binwidth = NULL, bins = NULL, na.rm = FALSE, orientation = NA, pad = FALSE
#> position_stack

penguins |>
  gg_blanket(
    geom = "bar",
    stat = "bin",
    position = "stack",
    x = flipper_length_mm, 
    col = species,
  ) 

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.