Skip to content
R for the Rest of Us Logo

Going Deeper with R

Customize Your Fonts

Transcript

Click on the transcript to go to that point in the video. Please note that transcripts are auto generated and may contain minor inaccuracies.

View code shown in video
# Load Packages -----------------------------------------------------------

library(tidyverse)
library(fs)
library(scales)
library(ggrepel)
library(ggtext)

# Create Directory --------------------------------------------------------

dir_create("data")

# Download Data -----------------------------------------------------------

# download.file("https://github.com/rfortherestofus/going-deeper-v2/raw/main/data/third_grade_math_proficiency.rds",
#               mode = "wb",
#               destfile = "data/third_grade_math_proficiency.rds")

# Import Data -------------------------------------------------------------

third_grade_math_proficiency <- 
  read_rds("data/third_grade_math_proficiency.rds") |> 
  select(academic_year, school, school_id, district, proficiency_level, number_of_students) |> 
  mutate(is_proficient = case_when(
    proficiency_level >= 3 ~ TRUE,
    .default = FALSE
  )) |> 
  group_by(academic_year, school, district, school_id, is_proficient) |> 
  summarize(number_of_students = sum(number_of_students, na.rm = TRUE)) |> 
  ungroup() |> 
  group_by(academic_year, school, district, school_id) |> 
  mutate(percent_proficient = number_of_students / sum(number_of_students, na.rm = TRUE)) |> 
  ungroup() |> 
  filter(is_proficient == TRUE) |> 
  select(academic_year, school, district, percent_proficient) |> 
  rename(year = academic_year) |> 
  mutate(percent_proficient = case_when(
    is.nan(percent_proficient) ~ NA,
    .default = percent_proficient
  )) |> 
  mutate(percent_proficient_formatted = percent(percent_proficient,
                                                accuracy = 1))


# Theme -------------------------------------------------------------------

theme_dk <- function() {
  
  theme_minimal() +
    theme(axis.title = element_blank(),
          plot.title = element_markdown(family = "IBM Plex Mono"),
          plot.title.position = "plot",
          panel.grid = element_blank(),
          axis.text = element_text(color = "grey60",
                                   family = "IBM Plex Mono",
                                   size = 10),
          legend.position = "none")
  
}

# Plot --------------------------------------------------------------------

top_growth_school <- 
  third_grade_math_proficiency |>
  filter(district == "Portland SD 1J") |> 
  group_by(school) |> 
  mutate(growth_from_previous_year = percent_proficient - lag(percent_proficient)) |> 
  ungroup() |> 
  drop_na(growth_from_previous_year) |>
  slice_max(order_by = growth_from_previous_year,
            n = 1) |> 
  pull(school)

third_grade_math_proficiency |>
  filter(district == "Portland SD 1J") |>
  mutate(highlight_school = case_when(
    school == top_growth_school ~ "Y",
    .default = "N"
  )) |> 
  mutate(percent_proficient_formatted = case_when(
    highlight_school == "Y" & year == "2021-2022" ~ str_glue("{percent_proficient_formatted} of students
                                                             were proficient
                                                             in {year}"),
    highlight_school == "Y" & year == "2018-2019" ~ percent_proficient_formatted,
    .default = NA
  )) |> 
  mutate(school = fct_relevel(school, top_growth_school, after = Inf)) |>
  ggplot(aes(x = year,
             y = percent_proficient,
             group = school,
             color = highlight_school,
             label = percent_proficient_formatted)) +
  geom_line() +
  geom_text_repel(hjust = 0,
                  lineheight = 0.9,
                  family = "IBM Plex Mono",
                  direction = "x") +
  scale_color_manual(values = c(
    "N" = "grey90",
    "Y" = "orange"
  )) +
  scale_y_continuous(labels = percent_format()) +
  scale_x_discrete(expand = expansion(add = c(0.05, 0.5))) +
  annotate(geom = "text",
           x = 2.02,
           y = 0.6,
           hjust = 0,
           lineheight = 0.9,
           family = "IBM Plex Mono",
           color = "grey70",
           label = str_glue("Each grey line
                            represents one school")) +
  labs(title = str_glue("<b style='color: orange;'>{top_growth_school}</b> showed large growth in math proficiency over the last two years")) +
  theme_dk()

Your Turn

  1. Set you system up to use custom fonts using the ragg and systemfonts packages.

  2. Apply a custom font to your plot.

  3. Save your plot using ggsave()and add your plot to a Quarto document to make sure that it renders correctly there.

If you want to use the fonts I do, you can download them:

Learn More

Cara Thompson has a great article on getting fonts to work in R.

If you want to go really deep on custom fonts in R, check out this article by June Choe.

Have any questions? Put them below and we will help you out!

You need to be signed-in to comment on this post. Login.

Karina Wheeler

Karina Wheeler • November 16, 2023

When I downloaded the systemfonts package, I do not have the IBM Plex Mono or Inter Tight font. I do have a variety of other fonts. Do you know the reason why the fonts are different for me?

David Keyes

David Keyes Founder • November 16, 2023

I should have clarified. The systemfonts package does not install any fonts for you. It just gives you access to fonts that are on your system. If you wanted to work with the fonts I show in the video you could download them (click the Download Family button in the top right corner for each):

After that, you need to install the fonts on your system. After all of this, you can work with them in ggplot. Let me know if that works for you!

Rachel Udow

Rachel Udow • May 23, 2024

After setting up my system to work with custom fonts (by installing and loading the ragg and systemfonts packages, and also changing Backed -> AGG in global settings), my plots are no longer rendering in the Plots pane, though ggsave is working fine. Any idea what I may have missed here? Thanks!

Libby Heeren

Libby Heeren Coach • May 23, 2024

Hey, Rachel! Not sure what could be causing this. I'd say try restarting your R session and running some plots without loading the packages to see what happens. You could also try changing your backend graphics setting back to default, restarting R, and trying some plots again. Get with me via Discord or email and we can troubleshoot it together if you like!

Libby Heeren

Libby Heeren Coach • May 23, 2024

Also check to make sure that the problem you're having viewing your plots isn't that you're assigning them to objects only (and then not running the object to see the plot) as that is a common misstep!

Odile DOREUS

Odile DOREUS • October 6, 2024

Can custom fonts be applied to any themes? I tried many on the economist one which did not work, but they were successfully applied to other themes.

Gracielle Higino

Gracielle Higino Coach • October 8, 2024

Hi Odile! We might need more information to find out what's happening in your case. The Economist theme uses a "sans" family by default, so I would suspect that an incompatibility with some font families could "break" the code. Can you send us an example using the penguins dataset?

Raouf Kilada

Raouf Kilada • December 6, 2024

I could not find ibm plex mono.....

David Keyes

David Keyes Founder • December 6, 2024

Here you go: https://fonts.google.com/specimen/IBM+Plex+Mono

Gracielle Higino

Gracielle Higino Coach • December 7, 2024

Hi Raouf! It's possible that you don't have this font installed on your computer. You can check by running the code below:

systemfonts::system_fonts() |> 
  filter("IBM" %in% family)

If you don't see the font, if R returns an empty tibble, try doing the exercise with another font family that is installed on your computer instead.

Course Content

44 Lessons