This document provides information on how to select fonts when drawing text in R graphics.
This section describes how we select a font for drawing text, for a variety of R packages and authoring environments.
NOTE that for most text drawing functions, we can only select a single font for the entire text that we are drawing. The Formatting Text in R Section describes a way to select different fonts within a single piece of text.
We specify a font using three parameters: family, face, and size.
Font size is just a number describing how big the text should be, e.g.,
12
means 12pt
(where a "pt" is 1/72 of an inch).
NOTE that the point
size does not actually guarantee the physical size of any
particular characters in the font. However, for the same font,
characters in 24pt should be twice the
size of characters in 12pt.
The font face is either "plain"
, "bold"
,
"italic"
,
or "bold.italic"
The font family is trickier because it depends on what graphics device
we are drawing on AND on which fonts are installed on our
system (see Specifying the font family below
for more details).
However, "sans"
(the default),
"serif"
, and
"mono"
should always produce something
(a sans-serif font, a serif font, and a monospace font, respectively).
In 'grid' the gpar()
function has three
arguments that specify the font for drawing text:
fontfamily
, fontface
, and
fontsize
. The cex
parameter
also affects fontsize
, as a multiplier.
For example, the code below draws the same text at the same size with a different font family on each row and a different font face in each column.
library(grid) face <- c("plain", "bold", "italic", "bold.italic") family <- c("sans", "serif", "mono") for (i in 1:3) { for (j in 1:4) { grid.text("hello world", x = j/5, y = i/4, gp=gpar(fontfamily = family[i], fontface = face[j])) } }
In 'ggplot2', geom_text()
obeys the aesthetics
family
, fontface
, and size
.
Text labelling, e.g., axis labels, can also be controlled via themes. The
element_text()
function accepts family
,
face
, and size
arguments.
NOTE that in 'ggplot2' size
is in mm rather than
points.
For example, the code below draws the same text at the same size
in several different families and faces with geom_text()
and draws all of the axis labels bold using element_text()
.
library(ggplot2) df <- cbind(expand.grid(family, face), y = rep(1:3, 4), x = rep(1:4, each = 3)) ggplot(df, aes(x = x, y = y)) + geom_text(aes(family = Var1, fontface = Var2), label = "hello world") + coord_cartesian(xlim = c(0, 5), ylim = c(0, 4)) + theme(axis.text = element_text(face = "bold"))
Specifying a font family is more complicated because it requires a different approach for different graphics devices.
The best way to keep font selection simple is to use a graphics device
that allows us to specify any font that is installed on our
operating system by just giving the font name.
For example, if my system has a font called
"DejaVu Sans" then all I need to do (in 'grid') is specify
fontfamily = "DejaVu Sans"
.
One way to do this is to use one of the "Cairo" graphics devices, e.g.,
png(type="cairo")
, cairo_pdf()
,
or svg()
.
Another option is the 'ragg' package, which provides the
agg_png()
graphics device and several others.
The Graphics Devices in R page provides more detail on selecting different R graphics devices, including information on selecting a graphics device within an R Markdown document.
The system_fonts()
function from the 'systemfonts'
package can be used to list the available system fonts.
This function returns a data frame with one row for each font
and columns containing information about each font;
the name
or family
columns in this
dataframe can
be used as the value for
fontfamily
(in 'grid') or family
(in 'ggplot2').
As mentioned at the top of this document, the standard text-drawing in R, in both 'grid' and 'ggplot2', can only use a single font to draw the entire text. This section describes a way to escape that restriction.
The 'gridtext' and 'ggtext' packages allow us to use a small subset of markdown (and/or HTML) within our text. This allows us to change the font family, face, size, and colour of text within a single piece of text.
For example, the following code uses the richtext_grob()
function from 'gridtext'
to draw a combination of bold, italic and plain text
using markdown syntax, AND it colours part of the text using
HTML (and CSS) syntax.
library(grid) library(gridtext) grid.draw(richtext_grob('This text contains **bold**, *italic*, and <span style="color: red">colourful</span> text.'))
The following code uses element_markdown()
from
'ggtext' to allow markdown (and HTML) in the labels
of a 'ggplot2' legend (so that the colours of the text
labels in the legend matches the colours of the data symbols
in the legends).
library(ggplot2) library(ggtext) library(dplyr) colours <- palette.colors(4, "ggplot2")[-1] mpg$drive <- recode(factor(mpg$drv), "4"=sprintf('<span style="color: %s">4WD</span>', colours[1]), "f"=sprintf('<span style="color: %s">front</span>', colours[2]), "r"=sprintf('<span style="color: %s">rear</span>', colours[3])) ggplot(mpg) + geom_point(aes(x = displ, y = cty, colour = drive)) + theme(legend.text = element_markdown()) + scale_colour_manual(values = colours)
The 'ggtext' package website provides more details and examples.