Here are all the nuts and bolts you need for working on legend item spacing!
Welcome to my first blog post in 2023! I have been slacking off a little bit lately and feel so glad to ring in the new year with another Legend Tips Series post.
In this post, I will show you how to adjust the spacing between discrete legend items (legend title, keys, and labels) as well as between multiple legends. This is going to be a handy one and let’s get to it!
We’ll start with a single legend: There are four main arguments in
theme()
when it comes to adjusting the spacing between
legend title, keys, and labels: legend.title
,
legend.text
, legend.spacing.x
, and
legend.spacing.y
. I’ll demonstrate them in the following
section for a vertical legend, a horizontal legend, and a legend with a
matrix layout.
(1) Vertical legend
To adjust the spacing between legend title and the first legend key,
change the bottom margin of the title by specifying
margin = margin(b = )
in the legend.title
argument. To adjust the spacing between legend keys and labels, use
legend.spacing.x = unit()
and specify an appropriate value.
Similarly, to adjust the spacing between legend keys, use
legend.spacing.y = unit()
and specify an appropriate value.
Note that for legend.spacing.y = unit()
to work, you
MUST specify byrow = T
in the
corresponding guides (in this case “color” guide). Otherwise, nothing
will happen!
library(tidyverse)
### Default plot
P_vertical_default <- ggplot(data = iris) +
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_smooth(aes(x = Sepal.Length, y = Sepal.Width, color = Species, fill = after_scale(color)), method = "lm", se = T) +
scale_color_brewer(palette = "Set1") +
labs(x = "Sepal length", y = "Sepal width") +
theme_classic(base_size = 13)
### Adjust the spacing between legend items
P_vertical_adjusted <- P_vertical_default +
theme(legend.title = element_text(margin = margin(b = 10)), # adjust the spacing between the legend title and the first legend key
legend.spacing.x = unit(0.2, "inch"), # adjust the horizontal spacing between legend keys and labels
legend.spacing.y = unit(0.2, "inch")) + # adjust the vertical spacing between legend keys
guides(color = guide_legend(byrow = T)) # "byrow = T" is necessary for "legend.spacing.y" to work for vertical legends
P_vertical_default; P_vertical_adjusted
(2) Horizontal layout
Similar to vertical legends, to adjust the spacing between legend
title and the first legend key, change the right margin of the title by
specifying margin = margin(r = )
in the
legend.title
argument. To adjust the spacing between legend
keys and labels, use legend.spacing.x = unit()
and specify
an appropriate value. Additionally, you can use
legend.text = element_text(margin = margin(r = ))
to fine
tune the spacing between the label (e.g., the label “setosa”) and the
adjacent key (e.g., the blue key for “versicolor”).
legend.spacing.y = unit()
is not relevant to horizontal
legends here.
### Default plot
P_horizontal_default <- ggplot(data = iris) +
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_smooth(aes(x = Sepal.Length, y = Sepal.Width, color = Species, fill = after_scale(color)), method = "lm", se = T) +
scale_color_brewer(palette = "Set1") +
labs(x = "Sepal length", y = "Sepal width") +
theme_classic(base_size = 13) +
theme(legend.position = "top",
legend.direction = "horizontal")
### Adjust the spacing between legend items
P_horizontal_adjusted <- P_horizontal_default +
theme(legend.title = element_text(margin = margin(r = 10)), # adjust the spacing between legend title and the first legend key
legend.spacing.x = unit(0.2, "inch"), # adjust the spacing between legend keys and labels
legend.text = element_text(margin = margin(r = 15))) # fine tune the spacing between legend labels and adjacent legend keys
P_horizontal_default; P_horizontal_adjusted
(3) Matrix layout
We’ve seen both vertical and horizontal legends, how about a combination of both (matrix layout)? That’s actually easy-peasy: just put everything we did earlier together!
### Default plot
P_matrix_default <- ggplot(data = iris) +
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
geom_smooth(aes(x = Sepal.Length, y = Sepal.Width, color = Species, fill = after_scale(color)), method = "lm", se = T) +
scale_color_brewer(palette = "Set1") +
labs(x = "Sepal length", y = "Sepal width") +
theme_classic(base_size = 13) +
theme(legend.position = "top",
legend.direction = "horizontal") +
guides(color = guide_legend(nrow = 2, ncol = 2, byrow = T))
### Adjust the spacing between legend items
P_matrix_adjusted <- P_matrix_default +
theme(legend.title = element_text(margin = margin(r = 10)), # adjust the spacing between legend title and the first legend key
legend.spacing.x = unit(0.2, "inch"), # adjust the horizontal spacing between legend keys and labels
legend.spacing.y = unit(0.2, "inch"), # adjust the vertical spacing between legend keys
legend.text = element_text(margin = margin(r = 15))) # fine tune the spacing between the legend label and the adjacent legend key
P_matrix_default; P_matrix_adjusted
In the previous section, we focused on adjusting the spacing between the items within a legend. What if we have multiple legends and we want to change the spacing between them? Let’s see an example now:
### Default plot
P_multiple_default <- ggplot(data = iris) +
geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species, alpha = Sepal.Length*Sepal.Width)) +
geom_smooth(aes(x = Sepal.Length, y = Sepal.Width, color = Species, fill = after_scale(color)), method = "lm", se = T) +
scale_color_brewer(palette = "Set1") +
scale_alpha_continuous(name = "Sepal L*W") +
labs(x = "Sepal length", y = "Sepal width") +
theme_classic(base_size = 13)
P_multiple_default
Say we would like to increase the spacing between the two legends. We
can use the same hack as before by increasing the top margin of the
legend title, which will create more white space above both the title
“Sepal L*W” and “Species”. However, because of this extra white space,
the legends will be squeezed down a bit. To solve this problem, I used
legend.box.margin = margin(b = 50)
to increase the margin
below the legend box to push the legends up.
### Adjust the spacing between legends
P_multiple_adjusted <- P_multiple_default +
theme(legend.title = element_text(margin = margin(t = 30)), # create more white space above the legend titles
legend.box.margin = margin(b = 50)) # increase the margin below the legend box to push the legends up
P_multiple_adjusted
To recap, we learned how to adjust the spacing between the title, keys, and labels within a legend, as well as the spacing between multiple legends. Next time when you’re making ggplots, remember to apply these tips to polish your figure!
Hope you learn something useful from this post and don’t forget to leave your comments and suggestions below if you have any!
If you see mistakes or want to suggest changes, please create an issue on the source repository.