To simplify ggplot2 visualisation, ggblanket provides:
library(dplyr)
library(ggplot2)
library(ggblanket)
library(patchwork)
<- palmerpenguins::penguins |>
penguins mutate(sex = stringr::str_to_sentence(sex)) |>
::drop_na(sex) tidyr
Each gg_*
function wraps a ggplot2
ggplot(aes(...))
function with the applicable ggplot2
geom_*()
function. All aesthetics are placed directly in
the gg_*
function: they are not within a
ggplot2::aes
function. This also provides access to the
arguments of the relevant stat function.
# ggplot2
|>
penguins ggplot() +
geom_point(aes(x = flipper_length_mm,
y = body_mass_g))
# ggblanket
|>
penguins gg_point(
x = flipper_length_mm,
y = body_mass_g)
The colour and fill aesthetics of ggplot2 are merged into a single
concept represented by the col
argument. This argument
means that everything should be coloured according to it, i.e. all
points, lines and polygon interiors.
# ggplot2
<- penguins |>
p1 ggplot() +
geom_point(aes(x = flipper_length_mm,
y = body_mass_g,
col = species)) +
theme(legend.position = "bottom") +
guides(col = guide_legend(title.position = "top")) +
labs(col = "Species") +
scale_x_continuous(breaks = scales::breaks_pretty(n = 3))
<- penguins |>
p2 ggplot() +
geom_density(aes(x = body_mass_g,
fill = species)) +
theme(legend.position = "bottom") +
guides(fill = guide_legend(title.position = "top")) +
labs(fill = "Species")
+ p2 p1
# ggblanket
<- penguins |>
p1 gg_point(
x = flipper_length_mm,
y = body_mass_g,
col = species,
x_breaks = scales::breaks_pretty(n = 3),
col_legend_ncol = 2)
<- penguins |>
p2 gg_density(
x = body_mass_g,
col = species,
x_breaks = scales::breaks_pretty(n = 3),
col_legend_ncol = 2)
+ p2 p1
The pal
argument is used to customise the colours of the
geom. A user can provide a vector of colours to this argument. It can be
named or not. It works in a consistent way - regardless of whether a
col
argument is added or not. A named palette can be used
to make individual colours stick to particular values.
# ggplot2
<- penguins |>
p1 ggplot() +
geom_histogram(aes(x = body_mass_g),
fill = "#1B9E77") +
scale_x_continuous(breaks = scales::breaks_pretty(n = 3))
<- penguins |>
p2 ggplot() +
geom_jitter(aes(x = species,
y = body_mass_g,
col = sex)) +
scale_color_manual(values = c("#2596be", "#fc7c24"))
+ p2 p1
# ggblanket
<- penguins |>
p1 gg_histogram(
x = body_mass_g,
pal = "#1B9E77",
x_breaks = scales::breaks_pretty(n = 3))
<- penguins |>
p2 gg_jitter(
x = species,
y = body_mass_g,
col = sex,
pal = c("#2596be", "#fc7c24"))
+ p2 p1
Faceting is treated as if it were an aesthetic. Users just provide an
unquoted variable to facet by. If a single facet (or facet2) variable is
provided, it’ll default to a “wrap” layout. But users can change this
with a facet_layout = "grid"
argument.
# ggplot2
|>
penguins ggplot() +
geom_violin(aes(x = sex,
y = body_mass_g)) +
facet_wrap(~species)
# ggblanket
|>
penguins gg_violin(
x = sex,
y = body_mass_g,
facet = species)
A facet2
argument is also provided for extra
functionality and flexibility. If both facet
and
facet2
variables are provided, then it’ll default to a
“grid” layout of facet
by facet2
. But users
can change this with a facet_layout = "wrap"
argument.
# ggplot2
|>
penguins ggplot() +
geom_histogram(aes(x = flipper_length_mm)) +
facet_grid(species ~ sex)
# ggblanket
|>
penguins gg_histogram(
x = flipper_length_mm,
facet = sex,
facet2 = species)
Prefixed arguments are available to customise titles, scales, guides, and faceting. These are designed to work with the Rstudio auto-complete to help users remember and find the adjustment they need. Users should first determine whether they want to change something that relates to x, y, col or facet. Then they should type this prefix and press the tab key to access the list of options from the Rstudio auto-complete. Then they can use the arrow keys, and press tab again to select what they want.
# ggplot2
|>
penguins ggplot() +
geom_jitter(aes(x = species,
y = body_mass_g,
col = sex)) +
expand_limits(y = 0) +
scale_x_discrete(labels = \(x) stringr::str_sub(x, 1, 1)) +
scale_y_continuous(breaks = scales::breaks_width(1500),
labels = scales::label_number(big.mark = " "),
trans = "sqrt") +
labs(x = "Species", y = "Body mass (g)", col = "Sex") +
theme(legend.position = "top") +
theme(legend.justification = "left") +
scale_colour_manual(values = scales::hue_pal()(2),
guide = ggplot2::guide_legend(title.position = "top"))
# ggblanket
|>
penguins gg_jitter(
x = species,
y = body_mass_g,
col = sex,
x_labels = \(x) stringr::str_sub(x, 1, 1),
y_include = 0,
y_breaks = scales::breaks_width(1500),
y_labels = scales::label_number(big.mark = " "),
y_trans = "sqrt",
y_title = "Body mass (g)",
col_legend_place = "t")
Unspecified x/y/col titles are converted to sentence case with
snakecase::to_sentence. All titles can be manually changed using the
*_title
arguments. The default conversion is intended to
make titles sometimes able to be left as is.
# ggplot2
|>
penguins ggplot() +
geom_point(aes(x = flipper_length_mm,
y = body_mass_g,
col = sex)) +
facet_wrap(~species) +
scale_x_continuous(breaks = scales::breaks_pretty(n = 3))
# ggblanket
|>
penguins gg_point(
x = flipper_length_mm,
y = body_mass_g,
col = sex,
facet = species)
The ggplot2::theme_set
function can be used to set the
theme globally, such that all subsequent plots will use this where the
theme
argument of a plot is left as NULL. Alternatively,
users can use the theme
argument in a gg_*
function.
ggblanket provides two complete ggplot2 theme functions called
light_mode
(the default) and dark_mode
. The
first argument is the base_size
. This changes the size of
all the text to this, except the title is 10% higher and the caption is
10% lower. There are other arguments to change the family, face, colour,
size, margins and vertical adjustment of text.
Note that the gg_*
function will control what gridlines
are present and the placement of the legend - despite the theme
provided. Therefore, if you are providing a theme other than
light_mode
or dark_mode
, ggblanket works well
if this theme has both vertical and horizontal gridlines. If users want
everything adjusted as per the theme, then they can +
their
theme onto the plot instead.
Note that theme_set(theme_grey())
resets the set theme
for ggplot2 code to theme_grey and for ggblanket gg_*
functions to light_mode()
. If you want ggblanket
gg_*
functions to default to using
theme_grey()
, then you must modify the base_size slightly
(e.g. theme_set(theme_grey(11.01))
).
# ggblanket
theme_set(dark_mode())
|>
penguins gg_point(
x = flipper_length_mm,
y = body_mass_g,
col = sex,
title = "Penguins body mass by flipper length",
subtitle = "Palmer Archipelago, Antarctica",
caption = "Source: Gorman, 2020",
pal = c("#2596be", "#fc7c24"))
# ggblanket
theme_set(light_mode(base_size = 12))
|>
penguins gg_point(
x = flipper_length_mm,
y = body_mass_g,
col = sex,
title = "Penguins body mass by flipper length",
subtitle = "Palmer Archipelago, Antarctica",
caption = "Source: Gorman, 2020",
pal = c("#2596be", "#fc7c24"))
theme_set(theme_grey()) #unset the theme
Where the orientation is normal (i.e. vertical):
It does the opposite where the orientation is horizontal (and also keeps y categorical values in correct order).
Note gg_raster
deviates froms this approach, and instead
places the limits as the min and max of the data by default.
# ggplot2
|>
penguins group_by(species, sex) |>
summarise(body_mass_g = mean(body_mass_g)) |>
ggplot() +
geom_col(aes(x = body_mass_g,
y = species,
fill = sex),
position = "dodge",
width = 0.75)
# ggblanket
|>
penguins group_by(species, sex) |>
summarise(body_mass_g = mean(body_mass_g)) |>
gg_col(
x = body_mass_g,
y = species,
col = sex,
position = "dodge",
width = 0.75)
...
The ...
argument is placed in the gg_*
function within the wrapped ggplot2::geom_*
function. This
means all other arguments in the geom_*
function are
available to users (except the mapping argument). Common arguments from
...
to add are size
, linewidth
and width
.
# ggblanket
|>
penguins gg_smooth(
x = flipper_length_mm,
y = body_mass_g,
col = sex,
linewidth = 0.5, #accessed via geom_smooth
level = 0.99) #accessed via geom_smooth
Users can make plots with multiple layers with ggblanket by adding on
ggplot2::geom_*
layers. The gg_*
function puts
the aesthetics within the wrapped ggplot
function.
Therefore, the aesthetics will inherit to any subsequent geoms added.
Geoms will plot in order. The gg_*
function will plot the
associated geom as the first layer, and then other geoms will be plotted
on top of it.
# ggblanket + ggplot2
|>
penguins gg_boxplot(x = species,
y = body_mass_g,
width = 0.5,
outlier.colour = NA) +
geom_jitter(col = pal_blue)
If some geoms have a col
aesthetic and some do not, then
it is recommended to have the col
aesthetic in the
gg_*
function. This enables ggblanket legend placement, as
well as the ability to adjust the col scale via the gg_*
function.
If you do not want a col aesthetic in your bottom plot layer, but
require it in subsequent layers - then you should use the
gg_blank
function. Subsequent geom_*
layers
where the col aesthetic is not required can have col = NA
and/or fill = NA
arguments - or use the
inherit.aes = FALSE
argument.
Note the plot scales are constructed without knowledge of subsequent
layers. The gg_*
function builds the x and y scales based
on the data
, stat
, x
, and
y
in the gg_*
function. These scales can be
adjusted to accommodate subsequent layers using the
*_include
or *_limits
arguments.
# ggblanket + ggplot2
<- penguins |>
d group_by(species) |>
summarise(body_mass_g = mean(body_mass_g)) |>
mutate(lower = body_mass_g * 0.95) |>
mutate(upper = body_mass_g * 1.2)
<- d |>
p1 gg_blank(
y = species,
x = body_mass_g,
col = species,
xmin = lower,
xmax = upper,
x_include = 0,
x_labels = \(x) x / 1000,
x_title = "Body mass kg") +
geom_col(alpha = 0.9, width = 0.75) +
geom_errorbar(col = "black", width = 0.1)
<- d |>
p2 gg_blank(
y = species,
x = body_mass_g,
xmin = lower,
xmax = upper,
col = species,
x_include = 0,
x_labels = \(x) x / 1000,
x_title = "Body mass kg") +
geom_col(col = NA, fill = "#d3d3d3", width = 0.75) +
geom_errorbar(width = 0.1)
/ p2 p1
# ggblanket + ggplot2
<- gapminder::gapminder |>
d_wide filter(year %in% c(1967, 2007)) |>
select(country, year, lifeExp) |>
::pivot_wider(names_from = year, values_from = lifeExp) |>
tidyrmutate(gap = `2007` - `1967`) |>
slice_max(gap, n = 10) |>
mutate(country = forcats::fct_inorder(forcats::fct_drop(country)))
<- d_wide |>
d_long select(-gap) |>
::pivot_longer(-country,
tidyrnames_to = "year",
values_to = "life_expectancy")
|>
d_long gg_blank(x = life_expectancy,
y = country,
col = year,
pal = pal_hue[c(2, 1)],
x_include = 0,
col_legend_place = "r",
title = "We're living longer",
subtitle = "Biggest life expectancy rise, 1967\u20132007",
x_title = "Life expectancy",
y_title = "") +
geom_segment(aes(x = `1967`, xend = `2007`,
y = country, yend = country),
data = d_wide, inherit.aes = FALSE,
col = "#dddddd", linewidth = 2) +
geom_point(size = 2)
To extend ggblanket further, users can:
See the Extending further article for further information.