Ernesto
Ernesto

Reputation: 187

ggplot2 - Add extra space between two legend items

I've created a ggplot2 graph using the basic code below:

my_df %>% 
  ggplot(aes(conv_norm, vot_norm, color = language:poa)) + 
  geom_smooth(method = "glm", se=FALSE) + 
  theme(
  ...
  )

[I've left out the formatting commands from the theme() layer]

And I got a graph that looks like this: enter image description here

Now, my question is: how can I add extra space only in between two legend items? I've looked online and have found ways to increase the spacing between all items in the legend, but I only want extra spacing between the English items and the Spanish items. Is there a way to add a 1-in distance between these language groups?

Upvotes: 2

Views: 425

Answers (2)

tjebo
tjebo

Reputation: 23737

Another option would be to create two separate legends. Either by using two different aesthetics, or you can use color twice, e.g with ggnewscale - thanks to user chemdork123 for the fake data +1.

library(tidyverse)
library(ggnewscale)
set.seed(12345)
my_df <- data.frame(
  lang = rep(c(paste('English',1:3), paste('Spanish',1:3)),2),
  x = c(rep(0,6), rep(1,6)),
  y = rnorm(12, 10,2))

ggplot(mapping = aes(x,y)) +
  geom_line(data = filter(my_df, grepl("English", lang)), aes(color=lang)) +
  scale_color_brewer(NULL, palette = "Dark2") +
  new_scale_colour() +
  geom_line(data = filter(my_df, grepl("Spanish", lang)), aes(color=lang)) +
  scale_color_brewer(palette = "Set1") +
  guides(color = guide_legend(order = 1))

Created on 2021-04-11 by the reprex package (v1.0.0)

Upvotes: 2

chemdork123
chemdork123

Reputation: 13823

Well, I don't know of an elegant, simple solution to do what you are asking to do... but by working with how legends are drawn and adjusting some of the elements, we can come up with a really "hacky" solution. ;)

Here's a sample dataset that kind of simulates what you shared, along with the plot:

set.seed(12345)
my_df <- data.frame(
  lang = rep(c(paste('English',1:3), paste('Spanish',1:3)),2),
  x = c(rep(0,6), rep(1,6)),
  y = rnorm(12, 10,2))

library(ggplot2)

p <- ggplot(my_df, aes(x,y, color=lang)) + geom_line()
p

enter image description here

The approach here is going to be to combine all the following individual steps:

  • Add a "blank" legend entry. We do this by refactoring and specifying the levels of the column mydf$lang to include a blank entry in the correct position. This will be the final order of the items in the legend.

  • Use scale_color_manual() to set the colors of the legend items manually. I make sure to use "NA" for the blank entry.

  • Within scale_color_manual() I use the drop=FALSE setting. This includes all levels for a factor, even if there is no data on the plot to show. This makes our blank entry show on the legend.

  • Use the legend.background theme element to draw transparent boxes for the legend key items. This is so that you don't have a white or gray box for that blank entry.

Putting it all together you get this:

my_df$lang <- factor(my_df$lang, levels=c(paste('English',1:3), '', paste('Spanish',1:3)))

ggplot(my_df, aes(x,y, color=lang)) +
  geom_line() +
  scale_color_manual(
    values=c(rainbow(6)[1:3], 'NA', rainbow(6)[4:6]),
    drop=FALSE) +
  theme( legend.key = element_rect(fill='NA') )

enter image description here

Alternatively, you could use guides(color=guide_legend(override.aes... to set the colors, but you need the drop=FALSE part within scale_color_manual() get the blank level to draw in the legend anyway.

Upvotes: 2

Related Questions