Fonts in R

This document provides information on how to select fonts when drawing text in R graphics.

Font Selection

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.

Font parameters

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).

Font parameters in 'grid'

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]))
    }
}
plot of chunk unnamed-chunk-1

Font parameters in 'ggplot2'

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"))
plot of chunk unnamed-chunk-2

Specifying the font family

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.

Listing installed fonts

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').

Formatting Text in R

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

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.'))
plot of chunk unnamed-chunk-3

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)
plot of chunk unnamed-chunk-4

The 'ggtext' package website provides more details and examples.


Creative Commons License
This work is licensed under a Creative Commons Attribution 4.0 International License.