David M. David M. - 1 month ago 7
R Question

How to display color in two parts of a ggplot legend?

I'm trying to plot line plots of several different series, where each series will be drawn with a different line width, and each belongs to one of several groups which will determine the color.

What I'm struggling to do is to create a legend which shows the group names and colors, as well as the individual series names and the width/color combination for each.

To give a minimal working example:

# Create data
names <- c("A", "B", "C", "D", "E", "F")

df <- data.frame(
name = rep(names, 3),
group = rep(c(rep("X", 2), rep("Y", 2), rep("Z", 2)), 3),
x = c(rep(1, 6), rep(2, 6), rep(3, 6)),
y = c(runif(6, 0, 1), runif(6, 1, 2), runif(6, 2, 3)),
stringsAsFactors=FALSE
)


line.widths <- setName(runif(6, 0, 3), names)
group.colors <- setNames(c("#AA0000", "#00AA00", "#0000AA"), c("X", "Y", "Z"))
name.colors <- setNames(c(rep("#AA0000", 2), rep("#00AA00", 2), rep("#0000AA", 2)),
names)


And now the plot:

library(ggplot2)

# Names and groups separately
ggplot(df, aes_string(x="x", y="y", group="name")) +
geom_line(aes(size=name, color=group)) +
scale_size_manual(values=line.widths) +
scale_color_manual(values=group.colors)


Six lines, with three different colors and three different line sizes.

My question is whether it's possible to add the group colors to the
name
portion of the legend, without losing the
group
portion.

Thanks!

Answer

You are incredibly close (and thank you for the well researched and attempted question). You just need to add override.aes in the legend, like so:

ggplot(df, aes_string(x="x", y="y", group="name")) +
  geom_line(aes(size=name, color=group)) +
  scale_size_manual(values=line.widths) + 
  scale_color_manual(values=group.colors) +
  guides(size = guide_legend(override.aes = list(col = name.colors)))

enter image description here