[This article was first published on R – Statistical Odds & Ends, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

I was recently asked to convert all the fonts in my ggplot2-generated figures for a paper to Times New Roman. It turns out that this is easy, but it brought up a whole host of questions that I don’t have the full answer to.

If you want to go all out with using custom fonts, I suggest looking into the extrafont and showtext packages. This post will focus on what you can do without importing additional packages.

Let’s make a basic plot and see its default look (I am generating this on a Mac with the Quartz device):

library(ggplot2)
base_fig <- ggplot(data = economics, aes(date, pop)) +
geom_line() +
labs(title = "Total US population over time",
subtitle = "Population in thousands",
x = "Date",
y = "Total population (in thousands)")

base_fig


To change all text in the figure to Times New Roman, we just need to update the text option of the theme as follows:

base_fig +
theme(text = element_text(family = "Times New Roman"))


ggplot allows you to change the font of each part of the figure: you just need to know the correct option to modify in the theme. (For a full list of customizable components of the theme, see this documentation.)

base_fig +
theme(plot.title    = element_text(family = "mono"),
plot.subtitle = element_text(family = "sans"),
axis.title.x  = element_text(family = "Comic Sans MS"),
axis.title.y  = element_text(family = "AppleGothic"),
axis.text.x   = element_text(family = "Optima"),
axis.text.y   = element_text(family = "Luminari"))


For standard fonts (i.e. widely-used fonts used in large parts of academia and industry) the code above will suffice.

What fonts can I pass to element_text()? I couldn’t find an easy answer on this. This will depend on the OS you are using and the graphics device used to render the figure.

On a Mac, you can go to the “Font Book” application and have a look at the list of fonts there. Most fonts there should work. One exception I noticed is when using fonts having a different alphabet. (For example, using family = "Klee" in the code above did not work for me.)

What’s a graphic device? It’s the engine that renders your plot. Common graphics devices are Quartz and X11. This is something the user typically does not need to care about. See this link and ?Devices for more details.

What are “mono”, “sans” and “serif”? These are categories of “types of fonts” (see details here). When the user specifies one of these 3 keywords instead of a full font name (e.g. “Times New Roman”), the graphics engine uses its default font associated for that keyword.

For the Quartz device, you can use quartzFonts() to see what the default font for each of these keywords is:

quartzFonts()
# $serif # [1] "Times-Roman" "Times-Bold" "Times-Italic" "Times-BoldItalic" # #$sans
# [1] "Helvetica"             "Helvetica-Bold"        "Helvetica-Oblique"     "Helvetica-BoldOblique"
#
# \$mono
# [1] "Courier"             "Courier-Bold"        "Courier-Oblique"     "Courier-BoldOblique"