Changing fonts in ggplot2
Asked Answered
F

7

156

Once upon a time, I changed my ggplot2 font using windowsFonts(Times=windowsFont("TT Times New Roman")). Now, I can't get it off of this.

In trying to set family="" in ggplot2 theme(), I can't seem to generate a change in fonts as I compile the MWE below with different font families.

library(ggplot2)
library(extrafont)
loadfonts(device = "win")

a <- ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() +
        ggtitle("Fuel Efficiency of 32 Cars") +
        xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
        theme(text=element_text(size=16, 
#       family="Comic Sans MS"))
#       family="CM Roman"))
#       family="TT Times New Roman"))
#       family="Sans"))
        family="Serif"))


print(a)
print("Graph should have refreshed")

R is returning a warning font family not found in Windows font database, but there was a tutorial I was following (if I can find it again I will update the link here) that said this was normal and not a problem. Also, somehow this worked at one point because my graph once used some arial or helvitica type font. I think this has always been a present warning even during the initial times migration.

UPDATE

when I run windowsFonts() my output is

$serif [1] "TT Times New Roman"

$sans [1] "TT Arial"

$mono [1] "TT Courier New"

But, this is after I ran font_import() so I can only conclude that my fonts are not being saved in the right place. The code that ran the font_import() request actually loads the libraries with:

LocalLibraryLocation <- paste0("C:\\Users\\",Sys.getenv("USERNAME"),"\\Documents","\\R\\win-library\\3.2");
    .libPaths(c(LocalLibraryLocation, .libPaths()))
Fiora answered 30/12, 2015 at 4:2 Comment(3)
Is this a windows-specific question and answer? Does anyone want to generalize to Linux?Overcome
Also, windowsFonts disappeared from grDevices after 3.4.1. The code here needs updating.Overcome
@smci: see this and this. You just need to specify the right path in LinuxVanpelt
G
205

You just missed an initialization step I think.

You can see what fonts you have available with the command windowsFonts(). For example mine looks like this when I started looking at this:

> windowsFonts()
$serif
[1] "TT Times New Roman"

$sans
[1] "TT Arial"

$mono
[1] "TT Courier New"

After intalling the package extraFont and running font_import like this (it took like 5 minutes):

library(extrafont)
font_import()
loadfonts(device = "win")

I had many more available - arguable too many, certainly too many to list here.

Then I tried your code:

library(ggplot2)
library(extrafont)
loadfonts(device = "win")

a <- ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() +
  ggtitle("Fuel Efficiency of 32 Cars") +
  xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
  theme(text=element_text(size=16,  family="Comic Sans MS"))
print(a)

yielding this:

enter image description here

Update:

You can find the name of a font you need for the family parameter of element_text with the following code snippet:

> names(wf[wf=="TT Times New Roman"])
[1] "serif"

And then:

library(ggplot2)
library(extrafont)
loadfonts(device = "win")

a <- ggplot(mtcars, aes(x=wt, y=mpg)) + geom_point() +
  ggtitle("Fuel Efficiency of 32 Cars") +
  xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
  theme(text=element_text(size=16,  family="serif"))
print(a)

yields: enter image description here

Grumpy answered 30/12, 2015 at 11:21 Comment(9)
Thanks for the help, half way there. I can toggle now between mono||sans (these look no different so far) and serif``, but not the actually name like "TT Times New Roman", but additionally, I not sure that my loadFonts` was successful. When I call fonts() I have a list of nearly 300 fonts, but my guess is they weren't installed to the local environment making them accessible to the windows device. I am not sure if that makes any sense, but I tried to provide an update to my original question with snippets that might help. Thanks again!Fiora
Thanks for that names snippet update, it looks very helpful, how did your comic sans Ms example produce the right appearance if the family is the only string my installation recognizes.Fiora
Luck. In that font (and in a lot of others), the family name is the same as the family value. So wf[which(wf=="Comic Sans MS")] yields $``Comic Sans MS`` [1] "Comic Sans MS"Grumpy
Thanks, do you know if it's possible to direct or load the fonts from a particular place? I.e. Even for the install of load fonts or specifying the fonts? I don't get the additional windows visible fonts when repeating the summary display call...Fiora
Did you run font_import and loadfonts() right after each other?Grumpy
is there any chance this won't work on a work laptop due to not having admin access? i'm running the above process and it's not working for me... had a MacBook at my last job and this was never an issue, it just WORKS on a mac... thoughts?Lakieshalakin
You could definintely lock down a Windows laptop to prevent new fonts from being installed. And I imagine there are a lot of IT departments that would do exactly that and by design. And they could also probably lock down a MacBook too if they knew what they were doing.Grumpy
For me it loaded and loaded all fonts in a super slow pace (Windows computer) with no way to abort. "showtext" package highlighted in the other reply worked like a charmAdjective
So you voted this answer down then? I am amused. Explain your reasoning.Grumpy
V
75

Another option is to use showtext package which supports more types of fonts (TrueType, OpenType, Type 1, web fonts, etc.) and more graphics devices, and avoids using external software such as Ghostscript.

# install.packages('showtext', dependencies = TRUE)
library(showtext)

Import some Google Fonts

# https://fonts.google.com/featured/Superfamilies
font_add_google("Montserrat", "Montserrat")
font_add_google("Roboto", "Roboto")

Load font from the current search path into showtext

# Check the current search path for fonts
font_paths()    
#> [1] "C:\\Windows\\Fonts"

# List available font files in the search path
font_files()    
#>   [1] "AcadEref.ttf"                                
#>   [2] "AGENCYB.TTF"                           
#> [428] "pala.ttf"                                    
#> [429] "palab.ttf"                                   
#> [430] "palabi.ttf"                                  
#> [431] "palai.ttf"

# syntax: font_add(family = "<family_name>", regular = "/path/to/font/file")
font_add("Palatino", "pala.ttf")

font_families()
#> [1] "sans"         "serif"        "mono"         "wqy-microhei"
#> [5] "Montserrat"   "Roboto"       "Palatino"

## automatically use showtext for new devices
showtext_auto() 

Plot: need to open Windows graphics device as showtext does not work well with RStudio built-in graphics device

# https://github.com/yixuan/showtext/issues/7
# https://journal.r-project.org/archive/2015-1/qiu.pdf
# `x11()` on Linux, or `quartz()` on Mac OS
windows()

myFont1 <- "Montserrat"
myFont2 <- "Roboto"
myFont3 <- "Palatino"

library(ggplot2)

a <- ggplot(mtcars, aes(x = wt, y = mpg)) + 
  geom_point() +
  ggtitle("Fuel Efficiency of 32 Cars") +
  xlab("Weight (x1000 lb)") + ylab("Miles per Gallon") +
  theme(text = element_text(size = 16, family = myFont1)) +
  annotate("text", 4, 30, label = 'Palatino Linotype',
           family = myFont3, size = 10) +
  annotate("text", 1, 11, label = 'Roboto', hjust = 0,
           family = myFont2, size = 10) 

## On-screen device
print(a) 

## Save to PNG 
ggsave("plot_showtext.png", plot = a, 
       type = 'cairo',
       width = 6, height = 6, dpi = 150)  

## Save to PDF
ggsave("plot_showtext.pdf", plot = a, 
       device = cairo_pdf,
       width = 6, height = 6, dpi = 150)  

## turn showtext off if no longer needed
showtext_auto(FALSE) 

Edit: another workaround to use showtext in RStudio. Run the following code at the beginning of the R session (source)

trace(grDevices::png, exit = quote({
    showtext::showtext_begin()
}), print = FALSE)

Edit 2: Starting from version 0.9, showtext can work well with the RStudio graphics device (RStudioGD). Simply call showtext_auto() in the RStudio session and then the plots will be displayed correctly.

Vanpelt answered 18/8, 2018 at 6:41 Comment(6)
Thanks, I look forward to trying this out!Fiora
thank you a thousand times... the package makes it super easy to a) verify what font families you have available for ggplot by font_families() - b) look for the font file names by font_files() - c) adding the font file as a font family by font_add(family, font_file_name). Awesome!!!Analemma
@AgileBean: glad that I could help :)Vanpelt
important: you must all install the XQuartz package from xquartz.org first, or you will get a non-descript error on trying to load the library.Armallas
This solutions does not work for me. I still get the default font, both in the window and the Rstudio's plot window.Betjeman
When I want to save as pdf it gives an error.Roboto' not found in PostScript font databaseWrapped
L
35

A simple answer if you don't want to install anything new

To change all the fonts in your plot plot + theme(text=element_text(family="mono")) Where mono is your chosen font.

List of default font options:

  • mono
  • sans
  • serif
  • Courier
  • Helvetica
  • Times
  • AvantGarde
  • Bookman
  • Helvetica-Narrow
  • NewCenturySchoolbook
  • Palatino
  • URWGothic
  • URWBookman
  • NimbusMon
  • URWHelvetica
  • NimbusSan
  • NimbusSanCond
  • CenturySch
  • URWPalladio
  • URWTimes
  • NimbusRom

R doesn't have great font coverage and, as Mike Wise points out, R uses different names for common fonts.

This page goes through the default fonts in detail.

Luz answered 13/5, 2020 at 13:10 Comment(1)
For some reason, this works for me if family="mono" and sans. But, does not work for Helvetica neither Helvetica-Narrow. here I got a classical warning grid.Call.graphics(C_text, as.graphicsAnnot(x$label), ... : font family not found in Windows font database. I have not added any further libraries like library(extrafont) loadfonts(device = "win"). Could this be a problem? Thanks!Rosina
H
8

This might be of interest for people looking to add custom fonts to their ggplots inside a shiny app on shinyapps.io.

You can:

  1. Place custom font in www directory: e.g. IndieFlower.ttf from here
  2. Follow the steps from here

This leads to the following upper section inside the app.R file:

dir.create('~/.fonts')
file.copy("www/IndieFlower.ttf", "~/.fonts")
system('fc-cache -f ~/.fonts')

A full example app can be found here.

Hercules answered 14/3, 2019 at 9:37 Comment(0)
D
4

To change the font globally for ggplot2 plots.

theme_set(theme_gray(base_size = 20, base_family = 'Font Name' ))
Dishabille answered 19/7, 2020 at 17:48 Comment(0)
K
2

In Windows, it's super easy to change the font. You don't need any additional packages; just a couple of lines of code.

Suppose you wanted to change the default sans serif font from Arial to Calibri. The following will do this, and the font should appear in any ggplots that you create:

windowsFonts(sans = windowsFont("Calibri"))

When you save your ggplot using ggsave, the font should appear in the saved file.

Rather than using "sans", you could also add your own font to this list, although you would have to edit the text elements of your ggplot theme to incorporate the new font.

If you are using svglite to create an SVG file, you also need to specify your chosen font. For example:

ggsave("MyPlot.svg", system_fonts = list("sans" = "Calibri"))
Krol answered 9/4, 2023 at 10:34 Comment(1)
I spent hours trying to figure this out. Thank you so much! This helped me make data labels on plots from the sjPlot package behave the way I wanted them to.Phobia
B
0

I fixed my issue with geom_text not applying the family="Roboto" command in R markdown by ensuring the Yaml header had theme: null in it. It was set to "page" previously and was overriding only the geom_text line oddly enough...

Beersheba answered 17/6, 2022 at 18:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.