Changing fonts in ggplot2

214,308

Solution 1

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

Solution 2

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.

Solution 3

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.

Solution 4

Late to the party, but 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.

Solution 5

To change the font globally for ggplot2 plots.

theme_set(theme_gray(base_size = 20, base_family = 'Font Name' ))
Share:
214,308
EngBIRD
Author by

EngBIRD

Updated on January 06, 2022

Comments

  • EngBIRD
    EngBIRD over 2 years

    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()))
    
  • EngBIRD
    EngBIRD over 8 years
    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
    EngBIRD over 8 years
    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.
  • Mike Wise
    Mike Wise over 8 years
    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"
  • EngBIRD
    EngBIRD over 8 years
    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...
  • Mike Wise
    Mike Wise over 8 years
    Did you run font_import and loadfonts() right after each other?
  • EngBIRD
    EngBIRD over 5 years
    Thanks, I look forward to trying this out!
  • Agile Bean
    Agile Bean over 5 years
    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!!!
  • Tung
    Tung over 5 years
    @AgileBean: glad that I could help :)
  • ivo Welch
    ivo Welch over 5 years
    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.
  • GreenManXY
    GreenManXY over 3 years
    This solutions does not work for me. I still get the default font, both in the window and the Rstudio's plot window.
  • maycca
    maycca about 3 years
    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!
  • NCC1701
    NCC1701 almost 3 years
    When I want to save as pdf it gives an error.Roboto' not found in PostScript font database
  • dre
    dre over 2 years
    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?
  • Mike Wise
    Mike Wise over 2 years
    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.