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.
