150

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()))
AndrewGB
  • 16,126
  • 5
  • 18
  • 49
EngBIRD
  • 1,915
  • 3
  • 18
  • 22
  • 3
    Is this a windows-specific question and answer? Does anyone want to generalize to Linux? – smci Aug 16 '18 at 21:28
  • 3
    Also, [`windowsFonts` disappeared from grDevices after 3.4.1](https://www.rdocumentation.org/packages/grDevices/versions/3.4.1). The code here needs updating. – smci Aug 16 '18 at 22:19
  • 1
    @smci: see [this](https://stackoverflow.com/a/51906008/786542) and [this](https://stackoverflow.com/a/51888677/786542). You just need to specify the right path in Linux – Tung Oct 04 '18 at 16:27

7 Answers7

194

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

Mike Wise
  • 22,131
  • 8
  • 81
  • 104
  • 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! – EngBIRD Dec 30 '15 at 15:18
  • 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. – EngBIRD Dec 30 '15 at 15:50
  • 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"` – Mike Wise Dec 30 '15 at 15:52
  • 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... – EngBIRD Dec 30 '15 at 16:38
  • Did you run font_import and loadfonts() right after each other? – Mike Wise Dec 30 '15 at 16:53
  • 1
    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? – dre Oct 23 '21 at 21:13
  • 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. – Mike Wise Oct 24 '21 at 08:09
  • 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 charm – Simon Stolz Aug 22 '22 at 09:39
  • 1
    So you voted this answer down then? I am amused. Explain your reasoning. – Mike Wise Aug 22 '22 at 13:33
72

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.

Tung
  • 26,371
  • 7
  • 91
  • 115
  • 1
    Thanks, I look forward to trying this out! – EngBIRD Aug 19 '18 at 03:11
  • 2
    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!!! – Agile Bean Oct 03 '18 at 10:43
  • @AgileBean: glad that I could help :) – Tung Oct 03 '18 at 12:34
  • 1
    important: you must all install the XQuartz package from https://www.xquartz.org/ first, or you will get a non-descript error on trying to load the library. – ivo Welch Nov 01 '18 at 17:43
  • 1
    This solutions does not work for me. I still get the default font, both in the window and the Rstudio's plot window. – GreenManXY Aug 16 '20 at 10:41
  • When I want to save as pdf it gives an error.`Roboto' not found in PostScript font database` – NCC1701 May 14 '21 at 23:33
32

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.

D A Wells
  • 1,047
  • 12
  • 16
  • 5
    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! – maycca Mar 10 '21 at 09:37
7

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.

Pertinax
  • 417
  • 4
  • 17
symbolrush
  • 7,123
  • 1
  • 39
  • 67
4

To change the font globally for ggplot2 plots.

theme_set(theme_gray(base_size = 20, base_family = 'Font Name' ))
Antex
  • 1,364
  • 4
  • 18
  • 35
1

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