Wednesday, November 30, 2016

Simplified Fonts for ggplot2 in R

I struggled for a while to get fonts to work properly with ggplot2 charts in R under Windows. The solution turned out to be easier than it seemed. The "old" way was to use library("extrafonts") which would then scan your entire fonts directory each run (slowly). Then if you got that working and you wanted to export a chart to a PDF, say, you'd need to install Ghostscript and embed the fonts subsequent to generating it. Nowadays R can do it all internally, and with a bit of setup, not have to scan the fonts at all. That's thanks to the showtext and cairo libraries.

You just have to find the filename of the font you want from your fonts directory. (In windows, open control panel -> fonts, then view details and  you may need to add a "Font File name" column". If no name appears, it may be a grouping; open the grouping and do the same.) In my case I wanted to use the Perpetua font, which has the name PER_____.ttf.


install.packages("showtext") # once
install.packages("Cairo" # once
library("showtext")
library("Cairo") # for embedding fonts in PDF; may not need to be loaded here
library("ggplot2")

# add the desired font to the font database (you can add multiple)
font.add("perpetua", "PER_____.ttf")

# the following should only be necessary in windows, and often isn't documented
# for each font you add, do this, mapping the Windows name and type to a font family
# variable (Perpetua in this case) that you will refer to it as.
windowsFonts(Perpetua=windowsFont("TT Perpetua"))

# plot something
# and use perpetua font for text (by default - any text can be customized)
qplot(1:10) +
  + theme(text = element_text(family="Perpetua")) 

# save to file; using Cairo drivers to embed the fonts as needed
ggsave("mychart.eps", width=6.5, height=5.5, device=cairo_ps)
ggsave("mychart.pdf", width=6.5, height=5.5, device=cairo_pdf)

Note that you shouldn't need any special driver to save as an image file (jpg/png/...). I have encountered a few fonts that don't seem to embed correctly and I'm not sure why that is at the moment, but most fonts seem to work fine with this method; they are viewable on screen and in PDFs. This procedure should theoretically work cross-platform (except that the windowsFonts call will not be needed), which is another advantage to this method, although I have not yet tested this.

You can also use google fonts like so, so you don't even have to find one on your system:
font.add.google("Roboto", "roboto")

There is more about the showtext library here. Hope this helps you. Be sure to leave comments if you find any improvements to this method.