32 Themes
The theme of a plot refers to all the parts that are not linked to data. This includes titles, axis lables, as well as the labelling of the axis labels or legends (also known as guides). It also includes text characteristics (font, size, colour, bold, italics) and the colour and placement of axes, tick marks, boxes around the plot and legend.
There is a single function, theme
that controls most of these features, with many options. I’ll give examples showing how to control many aspects of the theme.
Within a presentation or report, we often want to use a consistent theme for all figures. You can define many features of a theme and store them in an object in your R environment. You can then use this theme for all your figures. Changing the theme for many figures is then possible with only a single change in one location.
There are many add on packages for working with themes. I’ll give examples from ggtext, ggthemes, and patchwork.
32.1 Example plots for customization
We’ll use a couple of plots repeatedly: one with facets, and one with many other elements, but no facets.
p1 <- penguins %>% ggplot(aes(x = body_mass_g, y = flipper_length_mm,
color = species, shape = sex)) +
geom_point()
p1
## Warning: Removed 11 rows containing missing values (geom_point).
p2 <- mpg %>%
unglue_unnest(trans, "{trans_type}({trans_code})") %>%
ggplot(aes(x = displ, y = hwy, color = trans_type)) +
geom_point() +
facet_wrap(~ factor(cyl))
p2
32.2 Built-in themes
There are many themes available that change the whole look of your plot. I’ve used theme_bw
many times already, so here are a couple of other examples. For each you can use the base_size
option (default value 11) to scale text elements and base_line_size
to scale line elements of the figure.
p1 + theme_linedraw(base_size = 15, base_line_size = 0.2)
## Warning: Removed 11 rows containing missing values (geom_point).
p2 + theme_dark(base_size = 20)
There are also add-in packages with more themes: ggthemes
has theme_tufte
and theme_economist
p1 + theme_economist() + scale_fill_economist()
## Warning: Removed 11 rows containing missing values (geom_point).
Another collection of themes is available in ggthemer. The main goal of this lesson is to give you the vocabulary and skills to customize the theme of your plot, so I won’t spend any more time on theme packages. On to the details!
32.3 Customizing text on a figure
The most common change I want to make to a plot’s theme (after axis and guide labels) is to increase the size of the text. This can be done using theme(text= ...)
or for specific elements, theme(axis.title=...)
(see the help page for more elements of the theme that can be set with a text element.) On the right side of the equals sign, you need the function element_text
which allows you to control 10 different characteristics of your text. Here is an example of a few of the features.
Themes are controlled hierarchically, so adjusting text
affects all text on the plot. Adjusting axis.title
affects both axis.title.x
and axis.title.y
.
p2 + theme(text = element_text(size = 15),
axis.text.x = element_text(angle = 45),
axis.title.y = element_text(color = "blue"),
strip.text = element_text(face = "bold"),
legend.text = element_text(hjust = 1),
legend.title = element_text(family = "serif"),
axis.title.x = element_text(color = "#FF00FF", size = 18, face = "italic", family = "mono"))
Compare this with the original version of the plot and play “spot the differences”.
32.4 Customizing borders, ticks, axis labels
There are many elements on a plot drawn with lines. These too can be customized all at once using theme(line = ...)
or element by element using, for example theme(axis.line.x=...)
or theme(axis.ticks.y=...)
. The grid lines can be adjusted using panel.grid.major
and panel.grid.minor
. These elements are named and controlled hierarchically as well. The right hand size of the expressions above must have an element_line
function which allows you to control color, size, linetype and other features like arrows.
p2 + theme(line = element_line(size = 1),
axis.ticks.y = element_line(color = "pink"),
axis.line.x = element_line(linetype = 3, size = 0.25),
panel.grid.minor.y = element_blank(),
panel.grid.major = element_line(linetype = 3, color = "black", size = 0.25))
32.5 Enhanced text
The ggtext
package allows you to use markdown and HTML code in any text element on your plot. You need to use element_markdown
(or element_textbox_simple
) instead of element_text
for each element you want to use this enhanced formatting method with.
Unlike other theme elements, you can’t easily use ggtext
formatting hierarchically: you can’t simply set all text to use elemment_markdown
or even both axis labels. You must control each element individually.
p1 + labs(title = "_Penguin data from **Palmer station**, Antarctica_<sup>1</sup>",
x = "<span style = 'color:red;'>body mass (g)</span>",
y = "flipper length (mm)",
caption = "<sup>1</sup>Collected by K. Gorman"
) +
theme(plot.title = element_markdown(lineheight = 1.2),
plot.caption = element_markdown(),
axis.title.x = element_textbox_simple(halign = 0.5)
)
## Warning: Removed 11 rows containing missing values (geom_point).
You can also add formatted boxes for the titles of facets and at any location on a plot.
p2 + theme(
strip.background = element_blank(),
strip.text = element_textbox(
size = 12,
color = "white", fill = "#5D729D", box.color = "#4A618C",
halign = 0.5, linetype = 1, r = unit(5, "pt"), width = unit(1, "npc"),
padding = margin(2, 0, 1, 0), margin = margin(3, 3, 3, 3)
)
)
text_annotations <- tibble(
label = c(
"Some text **in bold.**",
"Linebreaks<br>Linebreaks<br>Linebreaks",
"*x*<sup>2</sup> + 5*x* + *C*<sub>*i*</sub>",
"Some <span style='color:blue'>blue text **in bold.**</span>"
),
x = c(4000, 5200, 5700, 5000),
y = c(220, 200, 175, 150),
hjust = c(0.5, 0, 0, 1),
vjust = c(0.5, 1, 0, 0.5),
angle = c(0, 0, 45, -45),
# sex = c("male", "male", "male", "male")
)
p1 + geom_richtext(mapping = aes(x = x, y = y, label = label,
angle = angle, hjust = hjust, vjust = vjust),
data = text_annotations,
inherit.aes = FALSE,
fill = NA,
color = "black")
## Warning: Removed 11 rows containing missing values (geom_point).
32.6 Further reading
-
ggplot tidyverse documentation - like the
theme
help page, but shows the results of the examples - Documentation for ggtext