library(ggplot2)
library(grid)
library(systemfonts)
theme_org <- function(base_size = 12, base_family = NULL) {
# Check if systemfonts package is installed and which
# fonts are available
sf <- systemfonts::system_fonts()
# Check if the base family is available in system fonts
org_font <- set_org_font(base_family, sf)
# Determine the graph font based on available fonts
org_graph_font <- set_condensed_font(org_font, sf)
dark_color <- "#201547"
medium_color <- "#582c83"
strip_color <- "#F0F0F0"
ggplot2::theme_minimal(base_size = base_size,
base_family = org_font) %+replace%
ggplot2::theme(
plot.caption = ggplot2::element_text(
family = org_font,
size = ggplot2::rel(0.7),
hjust = 1,
color = medium_color
),
plot.title = ggplot2::element_text(
size = ggplot2::rel(1.6),
face = "bold",
family = org_font,
color = dark_color,
lineheight = ggplot2::rel(1.5),
hjust = 0,
margin = ggplot2::margin(2, 1, 4, 1, "pt")
),
plot.title.position = "panel",
plot.caption.position = "plot",
plot.subtitle = ggplot2::element_text(
size = ggplot2::rel(1.2),
family = org_font,
color = medium_color,
lineheight = ggplot2::rel(1.2),
hjust = 0,
margin = ggplot2::margin(1, 1, 10, 1, "pt")
),
axis.title = ggplot2::element_text(
size = ggplot2::rel(1.1),
family = org_graph_font,
color = dark_color
),
axis.text = ggplot2::element_text(
size = ggplot2::rel(0.9),
family = org_graph_font,
color = medium_color
),
legend.title = ggplot2::element_text(
size = ggplot2::rel(0.9),
family = org_graph_font,
face = "bold",
color = dark_color
),
legend.text = ggplot2::element_text(
size = ggplot2::rel(0.8),
family = org_graph_font,
color = dark_color,
lineheight = 0.9
),
strip.text = ggplot2::element_text(
size = ggplot2::rel(0.9),
family = org_font,
face = "plain",
color = dark_color,
margin = ggplot2::margin(3, 2, 3, 2, "pt")
),
strip.background = ggplot2::element_rect(fill = strip_color,
color = strip_color),
legend.key.spacing.x = grid::unit(1, "pt"),
legend.key.spacing.y = grid::unit(0, "pt")
)
}
#' Choose a condensed font based on base font with graceful fallbacks
#'
#' @param org_font Base font name (e.g., "Roboto")
#' @param sf A systemfonts::system_fonts() data frame
#' @return Name of the best available condensed font
#' @export
set_condensed_font <- function(org_font, sf) {
# Map base font → preferred condensed version
condensed_map <- c(
"Arial" = "Arial Narrow",
"Helvetica" = "Helvetica Condensed",
"Avenir" = "Avenir Next Condensed",
"Avenir Next" = "Avenir Next Condensed",
"Fira Sans" = "Fira Sans Condensed",
"Source Sans Pro" = "Source Sans Pro Condensed",
"Roboto" = "Roboto Condensed",
"Noto Sans" = "Noto Sans Condensed",
"Open Sans" = "Open Sans Condensed",
"Lato" = "Lato Light",
"PT Sans" = "PT Sans Narrow",
"Ubuntu" = "Ubuntu Condensed",
"Droid Serif" = "Droid Serif Condensed"
)
preferred <- condensed_map[[org_font]]
if (!is.null(preferred) && preferred %in% sf$family) {
return(preferred)
} else if ("Arial Narrow" %in% sf$family) {
return("Arial Narrow")
} else if ("Helvetica Condensed" %in% sf$family) {
return("Helvetica Condensed")
} else {
return(org_font)
}
}
set_org_font <- function(base_family, sf) {
has_arial <- "Arial" %in% sf$family
has_helvetica <- "Helvetica" %in% sf$family
# Determine the base font and graph font based on available fonts
if (!is.null(base_family)) {
if (base_family %in% sf$family) {
org_font <- base_family
} else if (has_arial) {
org_font <- "Arial"
} else if (has_helvetica) {
org_font <- "Helvetica"
} else {
org_font <- "sans"
}
} else if (has_arial) {
org_font <- "Arial"
} else if (has_helvetica) {
org_font <- "Helvetica"
} else {
org_font <- "sans"
}
return(org_font)
}
Writing your own theme
In the code chunk below, we provide a function that you can use to create a custom theme for your organization. You can use this theme in your own plots by calling theme_org()
.
1 What this theme provides
This theme is built on the theme_minimal()
theme from ggplot2
, and it provides a set of default settings that we find generally useful. It allows the analyst who uses it to do the following:
- Set the base font (
base_family
) for the entire plot - If that base font is not available, it will fall back to a set of preferred fonts (e.g.,
Arial
orHelvetica
) - If that base font is available, then it will attempt to use a condensed version of that font (e.g.,
Arial Narrow
orHelvetica Condensed
) for the graph text. - If the analyst chooses from a set of select base fonts, then the theme will attempt to use a condensed version of that font. If that font is not available, it will fall back to a set of preferred condensed fonts (e.g.,
Arial Narrow
orHelvetica Condensed
). - Set the base font size for the entire plot; all other font sizes are set relative to this base size so the plot can be easily adapted for a variety of use cases (e.g., presentations, reports, etc.).
- Makes the plot title bold and much larger than the other text.
2 How to use this theme
Here’s the process for using this theme:
- Copy the code below into your own
R
script file. - Save the file as
theme_org.R
in your project directory (or wherever you put your R scripts). - Load the
theme_org.R
file into yourR
session (or into your ownR
script) using thesource()
function. - Call the
theme_org()
function in your plots to apply the theme. - When you are fully satisfied with any customization that you are going to do, then distribute this
theme_org.R
file to your colleagues so they can use the same theme in their plots. This is just another way that you can make it easier for your analytical team’s customers to use your work.
3 Customizing this theme
You can customize this theme in a variety of ways:
- Change the values of
dark_color
,medium_color
, orstrip_color
to use different colors for the plot title, axis labels, and strip labels. - Set the value of the
base_family
:- Search for
base_family = NULL
in the code below. - Change the
NULL
to the name of the font you want to use. For example, if you wanted to use"Avenir Next"
as the base font, you would change it tobase_family = "Avenir Next"
.
- Search for
- Set the value of the
base_size
:- Search for
base_size = 12
in the code below. - Change the
12
to the size you want to use. For example, if you wanted to use a base size of14
, you would change it tobase_size = 14
.
- Search for
- If you want to add another associated condensed font, you can add it to the
condensed_map
in theset_condensed_font()
function. For example, if you wanted to add"Scott Sans"
as a base font with"Scott Sans Condensed"
as the condensed font, you would add the line"Scott Sans" = "Scott Sans Condensed"
to thecondensed_map
list. - If you want to change the relative sizes of any of the text, you can do so by changing the
rel()
values in thetheme()
function. For example, if you wanted to make the plot title smaller, you could changesize = ggplot2::rel(1.6)
tosize = ggplot2::rel(1.4)
. - Finally, you can also add any other changes to the
theme_minimal()
settings within this call totheme()
. For example, if you wanted to change the background color of the plot, you could addpanel.background = ggplot2::element_rect(fill = "green")
to thetheme()
function.
4 The code itself
The following is the code for the theme_org()
function. You can copy and paste this into your own R
script file to use it.