As a follow up to this famous thread. I decided to ask a new question because this is more specifically for vertical legends, and the given answers still don't provide a fully satisfactory solution. For polygon key glyphs, there was a suggestion to increase the size of the margin between the actual polygon glyph and the key border, with a modification of the underlying draw_key function. However, this doesn't really work if I want to keep a border, e.g., in black.
And when using other geoms (e.g., geom_line), I don't even see how to increase the margin between glyph and border - on a brief glance at the draw_key function used in ggplot2:::GeomLine
(it doesn't use an exported draw_key function), it is not clear to me where to modify this.
So, my question is if there is a way to change the actual space between the key glyphs that would allow to keep a border (e.g., color = "black"), and without increasing the glyph size.
library(ggplot2)
p <- ggplot(dplyr::filter(msleep, grepl("^C", order)),
aes(sleep_total, sleep_rem, color = order)) +
geom_line(na.rm = TRUE) +
theme(legend.key = element_rect(color = "black"))
p
Example plot: Key glyphs touching.
p + theme(legend.key.height = unit(.5, "in"))
Example that would look as if the glyphs are more spaced if I'd remove the color, but I want the key glyphs in the same size as above, just space between them.
The underlying draw_key in GeomLine
# ggplot2:::GeomLine$draw_key
#> ...
#> segmentsGrob(0.1, 0.5, 0.9, 0.5, gp = gpar(col = alpha(data$colour %||%
#> data$fill %||% "black", data$alpha), fill = alpha(params$arrow.fill %||%
#> data$colour %||% data$fill %||% "black", data$alpha),
#> lwd = (data$size %||% 0.5) * .pt, lty = data$linetype %||%
#> 1, lineend = "butt"), arrow = params$arrow)
#> ...
Created on 2021-12-29 by the reprex package (v2.0.1)
P.S. This question arose on answering this interesting question
Update early 2024: You can use legend.key.spacing
now. More details in this answer.
Example:
library(ggplot2)
ggplot(dplyr::filter(msleep, grepl("^C", order)),
aes(sleep_total, sleep_rem, color = order)) +
geom_line(na.rm = TRUE) +
theme(
legend.key = element_rect(color = "black"),
legend.key.spacing.y = unit(1, "cm")
)
Created on 2024-05-31 with reprex v2.1.0
Old answer:
There is a way to do this, but it is not very intuitive. It depends on the byrow
setting in the legend guide, whether the legend spacing is respected or not (don't ask me why!).
library(ggplot2)
ggplot(dplyr::filter(msleep, grepl("^C", order)),
aes(sleep_total, sleep_rem, color = order)) +
geom_line(na.rm = TRUE) +
guides(
color = guide_legend(byrow = TRUE)
) +
theme(legend.key = element_rect(color = "black"),
legend.spacing.y = unit(1, "cm"))
Created on 2021-12-30 by the reprex package (v2.0.0)
I've complained raised the suggestion that this is unintuitive elsewhere.
If you want the title to be in a relatively normal position, you can use the following incantation to the theme function, wherein 11 pt is the default legend spacing:
legend.title = element_text(
margin = margin(
b = -1 + grid::convertUnit(unit(11, "pt"), "cm", valueOnly = TRUE),
unit = "cm")
)