R ggplot2 - Legend Customization
• ggplot2 provides granular control over legend appearance through `theme()`, `guides()`, and scale functions, allowing you to position, style, and organize legends to match publication requirements
Key Insights
• ggplot2 provides granular control over legend appearance through theme(), guides(), and scale functions, allowing you to position, style, and organize legends to match publication requirements
• Multiple legends can be merged, removed, or customized independently using guide_legend() and guide_colorbar() with parameters for layout, spacing, and visual hierarchy
• Legend titles, labels, and keys are fully customizable through scale functions and theme elements, enabling precise control over typography, colors, and positioning
Understanding ggplot2 Legend Basics
ggplot2 automatically generates legends when you map variables to aesthetics like color, fill, size, or shape. The legend system is tightly integrated with scales, making customization both powerful and sometimes complex.
library(ggplot2)
library(dplyr)
# Basic plot with automatic legend
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
labs(color = "Cylinders")
Every aesthetic mapping creates a corresponding legend. Understanding this relationship is crucial for effective customization.
Positioning and Layout Control
Legend position is controlled through theme(legend.position). You can use keywords or precise coordinates.
# Keyword positioning
p <- ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3)
# Inside plot area with coordinates (0-1 scale)
p + theme(legend.position = c(0.85, 0.85))
# Standard positions
p + theme(legend.position = "bottom") # Also: "top", "left", "right", "none"
# Horizontal layout for bottom position
p + theme(
legend.position = "bottom",
legend.direction = "horizontal"
)
For multiple legends, control their arrangement with legend.box:
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl), shape = factor(am))) +
geom_point(size = 3) +
theme(
legend.position = "right",
legend.box = "vertical", # or "horizontal"
legend.box.just = "top"
)
Customizing Legend Appearance
The theme() function provides extensive control over legend aesthetics through legend.* parameters.
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
theme(
legend.background = element_rect(fill = "lightgray", color = "black", linewidth = 0.5),
legend.key = element_rect(fill = "white", color = NA),
legend.key.size = unit(1.5, "cm"),
legend.key.width = unit(2, "cm"),
legend.title = element_text(size = 14, face = "bold"),
legend.text = element_text(size = 12, color = "darkblue"),
legend.spacing.y = unit(0.5, "cm")
)
Remove legend background and borders for cleaner presentations:
p + theme(
legend.background = element_blank(),
legend.key = element_blank(),
legend.box.background = element_blank()
)
Modifying Legend Titles and Labels
Scale functions control legend titles and labels directly:
# Customize through scale functions
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
scale_color_discrete(
name = "Engine\nCylinders",
labels = c("Four", "Six", "Eight")
)
# Remove legend title
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
scale_color_discrete(name = NULL)
# Format continuous legend
ggplot(mtcars, aes(x = wt, y = mpg, color = hp)) +
geom_point(size = 3) +
scale_color_continuous(
name = "Horsepower",
breaks = seq(100, 300, 50),
labels = paste0(seq(100, 300, 50), " HP")
)
Working with Multiple Legends
When multiple aesthetics are mapped, you get multiple legends. Control them individually using guides():
ggplot(mtcars, aes(x = wt, y = mpg, color = hp, size = qsec)) +
geom_point(alpha = 0.7) +
guides(
color = guide_colorbar(
title = "Horsepower",
barwidth = 1,
barheight = 10,
title.position = "top"
),
size = guide_legend(
title = "Quarter Mile Time",
title.position = "top",
nrow = 2
)
)
Merge legends when multiple aesthetics map to the same variable:
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl), shape = factor(cyl))) +
geom_point(size = 3) +
scale_color_discrete(name = "Cylinders") +
scale_shape_discrete(name = "Cylinders") # Same name merges legends
Remove specific legends while keeping others:
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl), size = hp)) +
geom_point(alpha = 0.7) +
guides(size = "none") # Remove size legend only
Advanced Guide Customization
The guide_legend() and guide_colorbar() functions offer detailed control over legend presentation.
# Custom legend layout
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
guides(color = guide_legend(
title = "Cylinders",
nrow = 3,
ncol = 1,
byrow = TRUE,
reverse = TRUE,
title.position = "top",
title.hjust = 0.5,
label.position = "right",
label.hjust = 0,
keywidth = 2,
keyheight = 1,
override.aes = list(size = 5) # Override aesthetic in legend
))
For continuous scales, customize color bars:
ggplot(mtcars, aes(x = wt, y = mpg, color = hp)) +
geom_point(size = 3) +
scale_color_gradient(low = "blue", high = "red") +
guides(color = guide_colorbar(
title = "Horsepower",
barwidth = 2,
barheight = 15,
ticks = TRUE,
ticks.colour = "black",
ticks.linewidth = 1,
frame.colour = "black",
frame.linewidth = 0.5,
title.position = "top",
title.hjust = 0.5
))
Handling Fill and Color Legends
Distinguish between color (lines/points) and fill (areas) aesthetics:
# Both color and fill
ggplot(mtcars, aes(x = factor(cyl), y = mpg, fill = factor(cyl))) +
geom_boxplot(aes(color = factor(cyl)), linewidth = 1) +
scale_fill_manual(
name = "Cylinders",
values = c("4" = "lightblue", "6" = "lightgreen", "8" = "lightcoral")
) +
scale_color_manual(
name = "Cylinders",
values = c("4" = "darkblue", "6" = "darkgreen", "8" = "darkred")
)
Legend Order and Arrangement
Control the order of legend items through factor levels or manual specification:
# Reorder through factor levels
mtcars$cyl_ordered <- factor(mtcars$cyl, levels = c(8, 6, 4))
ggplot(mtcars, aes(x = wt, y = mpg, color = cyl_ordered)) +
geom_point(size = 3) +
scale_color_discrete(name = "Cylinders")
# Reverse legend order
ggplot(mtcars, aes(x = wt, y = mpg, color = factor(cyl))) +
geom_point(size = 3) +
guides(color = guide_legend(reverse = TRUE))
Publication-Ready Legend Styling
Combine multiple customizations for professional output:
ggplot(mtcars, aes(x = wt, y = mpg, color = hp, shape = factor(am))) +
geom_point(size = 3, alpha = 0.8) +
scale_color_viridis_c(
name = "Horsepower",
option = "plasma",
breaks = seq(100, 300, 50)
) +
scale_shape_manual(
name = "Transmission",
values = c(16, 17),
labels = c("Automatic", "Manual")
) +
guides(
color = guide_colorbar(
barwidth = 1.5,
barheight = 12,
title.position = "top",
title.hjust = 0.5
),
shape = guide_legend(
title.position = "top",
title.hjust = 0.5,
override.aes = list(size = 4)
)
) +
theme_minimal() +
theme(
legend.position = "right",
legend.box = "vertical",
legend.title = element_text(size = 11, face = "bold"),
legend.text = element_text(size = 10),
legend.key = element_rect(fill = "white", color = NA),
legend.spacing.y = unit(0.3, "cm")
)
This comprehensive approach to legend customization ensures your visualizations meet exact specifications for publications, presentations, or reports. Master these techniques to transform default ggplot2 legends into polished, professional components that enhance rather than distract from your data story.