R ggplot2 Themes

Themes control the non-data visual elements of a ggplot2 chart — the background color, grid lines, font sizes, axis tick marks, legend position, and more. ggplot2 ships with several built-in themes and lets you customize every element with the theme() function.

Built-in Themes

library(ggplot2)

p <- ggplot(data.frame(x=1:5, y=c(3,1,4,1,5)), aes(x,y)) +
       geom_line(color="steelblue", linewidth=1.5) +
       labs(title="Theme Comparison")

p + theme_gray()        # default: gray background, white gridlines
p + theme_bw()          # white background, black border
p + theme_minimal()     # white background, subtle gridlines (most popular)
p + theme_classic()     # white background, no gridlines, classic axes
p + theme_dark()        # dark background
p + theme_light()       # light gray axes
p + theme_void()        # completely blank
p + theme_linedraw()    # black lines on white
Most popular choices:
  theme_minimal()  → clean, modern, publications
  theme_bw()       → classic academic style
  theme_classic()  → simple axes, no grid

Customizing with theme()

p + theme_minimal() +
  theme(
    plot.title      = element_text(size=16, face="bold", hjust=0.5),
    axis.title      = element_text(size=12, face="italic"),
    axis.text       = element_text(size=10, color="gray30"),
    panel.grid.major = element_line(color="gray90"),
    panel.grid.minor = element_blank(),
    plot.background  = element_rect(fill="white"),
    plot.margin      = margin(10, 20, 10, 20)
  )

theme() Element Functions

Element function        Controls
─────────────────────────────────────────────────────────────────
element_text(...)       Text: size, face, color, hjust, vjust, angle
element_line(...)       Lines: color, linewidth, linetype
element_rect(...)       Rectangles: fill, color, linewidth
element_blank()         Removes the element entirely

Common Theme Customizations

theme(
  # Title
  plot.title       = element_text(size=18, face="bold", hjust=0.5),
  plot.subtitle    = element_text(size=12, color="gray50", hjust=0.5),
  plot.caption     = element_text(size=8,  color="gray60", hjust=1),

  # Axes
  axis.title.x     = element_text(size=12, margin=margin(t=10)),
  axis.title.y     = element_text(size=12, margin=margin(r=10)),
  axis.text.x      = element_text(angle=45, hjust=1),  # rotate labels
  axis.ticks       = element_blank(),

  # Grid
  panel.grid.major = element_line(color="gray92"),
  panel.grid.minor = element_blank(),

  # Legend
  legend.position  = "bottom",      # "top","left","right","none"
  legend.title     = element_text(face="bold"),
  legend.background = element_rect(fill="gray98"),

  # Strip (facet labels)
  strip.background = element_rect(fill="steelblue"),
  strip.text       = element_text(color="white", face="bold")
)

Scales — Colors, Labels, Axes

library(ggplot2)

# Manual colors
scale_color_manual(values=c("A"="steelblue","B"="tomato"))
scale_fill_manual(values=c("Low"="#E8F5E9","High"="#1B5E20"))

# Brewer palettes (colorblind-friendly options available)
scale_fill_brewer(palette="Set2")     # categorical
scale_fill_distiller(palette="Blues") # continuous

# Viridis (colorblind-safe, prints well in grayscale)
scale_fill_viridis_c()    # continuous
scale_fill_viridis_d()    # discrete

# Axis formatting
scale_y_continuous(labels=scales::comma)       # 1,000,000
scale_y_continuous(labels=scales::percent)     # 45%
scale_x_date(date_labels="%b %Y")             # Jan 2024
scale_x_continuous(breaks=seq(0,100,by=10))   # custom breaks

Creating a Reusable Custom Theme

my_theme <- function() {
  theme_minimal() +
  theme(
    plot.title       = element_text(size=16, face="bold", color="#1a1a2e"),
    plot.subtitle    = element_text(size=11, color="#555555"),
    panel.grid.major = element_line(color="#f0f0f0"),
    panel.grid.minor = element_blank(),
    axis.title       = element_text(size=11, color="#333333"),
    legend.position  = "bottom"
  )
}

# Apply your theme to any chart
ggplot(data.frame(x=1:5, y=c(2,5,3,8,4)), aes(x,y)) +
  geom_line(color="steelblue", linewidth=1.5) +
  labs(title="My Custom Theme", subtitle="Clean and minimal") +
  my_theme()

Publication-Ready Chart Template

ggplot(exam, aes(x=class, y=score, fill=class)) +
  geom_boxplot(show.legend=FALSE, alpha=0.8) +
  scale_fill_brewer(palette="Set2") +
  labs(
    title    = "Exam Score Distribution by Class",
    subtitle = "Academic Year 2024",
    x        = NULL,
    y        = "Score (out of 100)",
    caption  = "Source: estudy247.com | n=60 students"
  ) +
  theme_minimal() +
  theme(
    plot.title    = element_text(size=16, face="bold", hjust=0.5),
    plot.subtitle = element_text(hjust=0.5, color="gray50"),
    plot.caption  = element_text(color="gray60", size=8)
  )

Themes are what separate exploratory charts (quick and rough) from presentation charts (polished and professional). Invest time in a custom theme that matches your organization's style — once defined, applying it to every chart takes one function call.

Leave a Comment

Your email address will not be published. Required fields are marked *