Customizing ggplot2 Charts
Once you’ve mastered the basics of ggplot2, the real power comes from customization. This tutorial covers how to fine-tune every aspect of your plots—from titles and labels to colors, themes, and legends.
Prerequisites
library(ggplot2)
library(dplyr)
# Sample data for examples
mpg_summary <- mpg |>
group_by(manufacturer) |>
summarise(avg_hwy = mean(hwy), count = n())
Modifying Axis Labels and Titles
The labs() function is your go-to for adding and customizing labels:
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy)) +
geom_col(fill = "steelblue") +
labs(
title = "Average Highway MPG by Manufacturer",
subtitle = "Based on EPA mileage data",
x = "Car Manufacturer",
y = "Average Highway MPG",
caption = "Data: EPA mpg dataset"
) +
theme_minimal()
You can also use ggtitle(), xlab(), and ylab() individually, but labs() is more concise.
Customizing Colors
Continuous Color Scales
For continuous variables, use scale_fill_gradient() or scale_color_gradient():
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy, fill = avg_hwy)) +
geom_col() +
scale_fill_gradient(
low = "lightblue",
high = "darkblue",
name = "MPG"
) +
theme_minimal()
Discrete Color Scales
For categorical data, use scale_fill_manual() to specify exact colors:
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy, fill = manufacturer)) +
geom_col() +
scale_fill_manual(
values = c("audi" = "#E41A1C", "chevrolet" = "#377EB8",
"ford" = "#4DAF4A", "honda" = "#984EA3"),
name = "Manufacturer"
) +
theme_minimal() +
theme(legend.position = "none")
The viridis scale is excellent for perceptually uniform colors:
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy, fill = avg_hwy)) +
geom_col() +
scale_fill_viridis_c(option = "plasma", name = "MPG") +
theme_minimal()
Using Themes
ggplot2 comes with several built-in themes:
# Different theme options
theme_gray() # Default gray background
theme_bw() # Black and white
theme_minimal() # Minimal, no background
theme_classic() # Classic look with axes
theme_dark() # Dark background
Apply a theme globally with theme_set():
theme_set(theme_minimal())
Customizing Theme Elements
Use theme() to modify specific elements:
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy)) +
geom_col(fill = "steelblue") +
labs(title = "Average Highway MPG") +
theme(
plot.title = element_text(size = 16, face = "bold", hjust = 0.5),
axis.text.x = element_text(angle = 45, hjust = 1),
panel.grid.major.x = element_blank(),
legend.position = "top"
)
Common theme elements:
plot.title,plot.subtitle,plot.captionaxis.title,axis.text,axis.linelegend.position,legend.title,legend.textpanel.background,panel.grid
Modifying Legends
Changing Legend Position
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy, fill = manufacturer)) +
geom_col() +
theme(legend.position = "top") # "bottom", "left", "right", "none"
Customizing Legend Labels
ggplot(mpg_summary, aes(x = manufacturer, y = avg_hwy, color = manufacturer)) +
geom_point(size = 3) +
scale_color_discrete(name = "Car Maker") +
theme(legend.title = element_text(face = "bold"))
Removing the Legend Altogether
+ theme(legend.position = "none")
Changing Scales
Modifying Axis Limits
# Using coord_cartesian() - preserves the data
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
coord_cartesian(xlim = c(1, 7), ylim = c(10, 50))
# Using scale functions - actually filters the data
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(limits = c(1, 7)) +
scale_y_continuous(limits = c(10, 50))
Customizing Tick Marks
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
scale_x_continuous(
breaks = c(2, 4, 6),
labels = c("2L", "4L", "6L")
) +
scale_y_continuous(
breaks = seq(10, 50, by = 10)
)
Faceting
Faceting creates small multiples showing subsets of data:
# Column faceting
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, ncol = 3) +
theme_minimal()
# Grid faceting
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_grid(drv ~ cyl) +
theme_minimal()
Customize facet labels:
ggplot(mpg, aes(x = displ, y = hwy)) +
geom_point() +
facet_wrap(~ class, labeller = label_both) +
theme(strip.text = element_text(face = "bold"))
Saving Your Plots
Use ggsave() to export plots:
# Save as PNG
ggsave("my_plot.png", width = 8, height = 6, dpi = 300)
# Save as PDF
ggsave("my_plot.pdf", width = 8, height = 6)
# Save with specific dimensions
ggsave("plot.png", width = 10, height = 8, units = "cm")
Summary
Key customization functions:
labs()— Add titles, labels, captionsscale_fill_*()/scale_color_*()— Customize colorstheme()— Modify visual appearancecoord_*()— Change coordinate systemsfacet_*()— Create small multiplesggsave()— Export plots to files
With these tools, you can transform basic ggplot2 visualizations into publication-ready charts that communicate your data effectively.