ggplot2 Theme Gallery

Author
Affiliation

Asst. Prof. Calvin J. Chiou

National Chengchi University (NCCU)

1 Setup

In this document, we explore various themes and styles available in ggplot2 and related packages. All examples use a line chart with three series drawn from the built-in economics_long dataset (unemployment rate, personal consumption expenditure, and personal savings rate — rescaled to a common 0–100 index for comparability).

library(ggplot2)

# ── Base data: three economic series, re-indexed to 0–100 ──────────────────
rescale01 <- function(x) (x - min(x)) / (max(x) - min(x)) * 100

econ <- subset(economics_long,
               variable %in% c("uempmed", "pce", "psavert"))
econ$variable <- factor(econ$variable,
                        levels  = c("uempmed", "pce", "psavert"),
                        labels  = c("Unemployment", "Consumption", "Savings"))

# Index each series to [0, 100]
econ$value_idx <- ave(econ$value01, econ$variable,
                      FUN = function(x) rescale01(x))

# Base plot object (reused throughout)
p <- ggplot(econ, aes(x = date, y = value_idx, color = variable)) +
  geom_line(linewidth = 0.8) +
  labs(x = "Year", y = "Index (0 – 100)",
       color = "Series",
       caption = "Source: ggplot2::economics_long")

2 Built-in ggplot2 Themes

Below are examples of every built-in theme shipped with ggplot2.

2.1 Theme Gray (default)

p + theme_gray() +
  labs(title = "Theme Gray")

2.2 Theme Dark-on-light (BW)

p + theme_bw() +
  labs(title = "Theme BW")

2.3 Theme Linedraw

p + theme_linedraw() +
  labs(title = "Theme Linedraw")

2.4 Theme Light

p + theme_light() +
  labs(title = "Theme Light")

2.5 Theme Dark

p + theme_dark() +
  labs(title = "Theme Dark")

2.6 Theme Minimal

p + theme_minimal() +
  labs(title = "Theme Minimal")

2.7 Theme Classic

p + theme_classic() +
  labs(title = "Theme Classic")

2.8 Theme Void

p + theme_void() +
  labs(title = "Theme Void")

2.9 Theme Test

p + theme_test() +
  labs(title = "Theme Test")


3 Themes in ggthemes

Additional themes and matching color scales from the ggthemes package (v 5.2.0, released 2025-11-30).

3.1 Theme Base

Mimics base R graphics aesthetics. New to the gallery — added in ggthemes 4.x.

library(ggthemes)

p + theme_base() +
  labs(title = "Theme Base")

3.2 Theme Economist

p + theme_economist() +
  scale_color_economist() +
  labs(title = "Theme Economist")

3.3 Theme Economist – White

p + theme_economist_white() +
  scale_color_economist() +
  labs(title = "Theme Economist – White")

3.4 Theme Excel (Classic)

p + theme_excel() +
  scale_color_excel() +
  labs(title = "Theme Excel (Classic)")

3.5 Theme Excel – New

p + theme_excel_new() +
  scale_color_excel_new() +
  labs(title = "Theme Excel – New")

3.6 Theme LibreOffice Calc

p + theme_calc() +
  scale_color_calc() +
  labs(title = "Theme Calc")

3.7 Theme Highcharts

p + theme_hc() +
  scale_color_hc() +
  labs(title = "Theme Highcharts")

3.8 Theme Google Docs

p + theme_gdocs() +
  scale_color_gdocs() +
  labs(title = "Theme Google Docs")

3.9 Theme Clean

p + theme_clean() +
  scale_color_canva() +
  labs(title = "Theme Clean")

3.10 Theme 538

p + theme_fivethirtyeight() +
  labs(title = "Theme 538")

3.11 Theme igray

p + theme_igray() +
  labs(title = "Theme igray")

3.12 Theme Few

p + theme_few() +
  scale_color_few() +
  labs(title = "Theme Few")

3.13 Theme Solarized

# Light
p + theme_solarized() +
  scale_color_solarized() +
  labs(title = "Theme Solarized – Light")

# Light 2
p + theme_solarized_2() +
  scale_color_solarized() +
  labs(title = "Theme Solarized 2")

# Dark
p + theme_solarized(light = FALSE) +
  scale_color_solarized() +
  labs(title = "Theme Solarized – Dark")

3.14 Theme Tufte

p + theme_tufte() +
  labs(title = "Theme Tufte")

3.15 Theme Stata

p + theme_stata() +
  scale_color_stata() +
  labs(title = "Theme Stata")

3.16 Theme Wall Street Journal (WSJ)

p + theme_wsj() +
  labs(title = "Theme Wall Street Journal")

3.17 Theme Pander

p + theme_pander() +
  scale_color_pander() +
  labs(title = "Theme Pander")


3.18 Notable Color Scales in ggthemes

The following demos use theme_minimal() as a neutral backdrop so the color scales are the focus.

3.18.1 Colorblind-safe Palette

scale_color_colorblind() (alias: scale_colour_colourblind()) provides an 8-color palette that is safe for the most common forms of color-vision deficiency. Renamed in ggthemes 5.2.0 to the British spelling.

p + theme_minimal() +
  scale_color_colorblind() +
  labs(title = "Colorblind-safe Palette (ggthemes)")

3.18.2 Paul Tol Qualitative Palette

scale_color_ptol() implements Paul Tol’s colorblind-safe qualitative palette, popular in scientific publishing.

p + theme_minimal() +
  scale_color_ptol() +
  labs(title = "Paul Tol Qualitative Palette (ggthemes)")

3.18.3 Tableau Color Scales

scale_color_tableau() offers Tableau’s discrete palettes. The default is the classic “Tableau 10”.

p + theme_minimal() +
  scale_color_tableau() +
  labs(title = "Tableau 10 Palette (ggthemes)")


4 Themes in tidyquant

library(tidyquant)

# Tidyquant – standard
p + theme_tq() +
  scale_color_tq() +
  labs(title = "Theme Tidyquant")

# Tidyquant – dark
p + theme_tq_dark() +
  scale_color_tq() +
  labs(title = "Theme Tidyquant Dark")

# Tidyquant – green
p + theme_tq_green() +
  scale_color_tq() +
  labs(title = "Theme Tidyquant Green")


5 Themes in hrbrthemes

hrbrthemes (v 0.8.x, Bob Rudis) is a typography-focused package offering publication-ready themes. It ships with a bundled copy of Roboto Condensed so no font installation is required for the core themes.

library(hrbrthemes)

# Suppress font warnings if Roboto Condensed is unavailable on this system
update_geom_font_defaults()

5.1 Theme ipsum

Clean, minimal, and opinionated — one of the most widely used non-ggplot2 themes in academic and data journalism contexts.

p + theme_ipsum() +
  labs(title = "Theme ipsum (hrbrthemes)")

5.2 Theme ipsum_rc (Roboto Condensed)

p + theme_ipsum_rc() +
  labs(title = "Theme ipsum_rc (hrbrthemes)")

5.3 Theme ft_rc (Financial Times – Dark)

Inspired by the Financial Times’s dark-background online charts.

p + theme_ft_rc() +
  labs(title = "Theme ft_rc – FT Dark (hrbrthemes)")

5.4 Theme modern_rc (Modern Dark)

p + theme_modern_rc() +
  labs(title = "Theme modern_rc – Modern Dark (hrbrthemes)")


6 Custom Theme

custom_theme <- theme(
  plot.title       = element_text(size = 14, face = "bold", hjust = 0.5),
  axis.title       = element_text(size = 12, face = "bold"),
  axis.text        = element_text(size = 10),
  panel.background = element_rect(fill = "white"),
  panel.grid.major = element_line(color = "grey80",   linewidth = 0.5),
  panel.grid.minor = element_line(color = "grey90",   linewidth = 0.25),
  legend.position  = "bottom"
)

p + custom_theme +
  labs(title = "Custom Theme")


7 Academic Journal Style

Academic journals (e.g., Journal of Finance, Review of Financial Studies) typically require figures that are black-and-white compatible, use grayscale or high-contrast linetype differentiation, have no chart junk, and are sized for a single or double column layout. The example below builds a self-contained theme_journal that satisfies these conventions, and uses linetypes instead of color so the figure survives grayscale printing.

# ── Journal theme definition ───────────────────────────────────────────────
theme_journal <- function(base_size = 10, base_family = "serif") {
  theme_classic(base_size = base_size, base_family = base_family) %+replace%
    theme(
      # Title & caption
      plot.title      = element_text(size = base_size, face = "bold",
                                     hjust = 0, margin = margin(b = 4)),
      plot.caption    = element_text(size = base_size - 2, hjust = 0,
                                     color = "grey40",
                                     margin = margin(t = 6)),
      # Axes
      axis.title      = element_text(size = base_size),
      axis.text       = element_text(size = base_size - 1, color = "black"),
      axis.line       = element_line(color = "black", linewidth = 0.4),
      axis.ticks      = element_line(color = "black", linewidth = 0.4),
      # No background, no minor grid; faint major grid only
      panel.grid.major = element_line(color = "grey88", linewidth = 0.3),
      panel.grid.minor = element_blank(),
      # Legend: compact, inside or below
      legend.title    = element_text(size = base_size - 1, face = "bold"),
      legend.text     = element_text(size = base_size - 1),
      legend.key.width = unit(1.5, "cm"),   # room to see the linetype
      legend.position = "bottom",
      legend.background = element_blank(),
      # Margins
      plot.margin     = margin(6, 8, 6, 6)
    )
}

# ── Plot: grayscale + linetype (no reliance on color) ─────────────────────
p_journal <- ggplot(econ,
                    aes(x = date, y = value_idx,
                        color    = variable,
                        linetype = variable)) +
  geom_line(linewidth = 0.6) +
  scale_color_grey(start = 0, end = 0.6) +      # black → mid-grey
  scale_linetype_manual(values = c("solid", "dashed", "dotdash")) +
  labs(
    title    = "U.S. Economic Indicators, 1967–2015",
    subtitle = NULL,
    x        = "Year",
    y        = "Index (0 – 100)",
    color    = NULL,
    linetype = NULL,
    caption  = "Note: Each series re-indexed to [0, 100]. Source: ggplot2::economics_long."
  ) +
  theme_journal()

p_journal

Key design choices that match journal submission guidelines:

  • Serif font ("serif") matches the body typeface of most economics journals.
  • scale_color_grey() + scale_linetype_manual() — the figure is fully legible in both color and grayscale print, satisfying most journals’ figure requirements.
  • fig.width = 5, fig.height = 3.5 targets a single-column figure width (~127 mm) common in two-column journal layouts.
  • fig.dpi = 300 meets the minimum resolution for most journals (300 dpi for line art).
  • No fill, no background shading, no minor gridlines — eliminates chart junk per Tufte’s principles.

To export the figure as a standalone file for submission:

ggsave("fig1.png", plot = p_journal,
       width = 5, height = 3.5, units = "in", device = "png")

ggsave("fig1.tiff", plot = p_journal,
       width = 5, height = 3.5, units = "in",
       dpi = 600, compression = "lzw")   # 600 dpi TIFF for some journals
Back to top