rggplot2legend

Avoid combined legends associated with different but grouped datasets


I am creating a scatter plot using ggplot2 with three groups. I am then adding an additional layer to plot additional data. In both cases, I map the data to group, but in the second case I want to legend to be dissociated from groups and just be a binary black and white linetype legend. Right now the legend merges everything.

Based on other solutions, I've tried scale_linetype_identity() and scale_linetype_manual(), to no avail.

Reprex:

library(ggplot2)

# Data 1
data1 <- data.frame(
  x = c(1, 2, 3), 
  y = c(10, 20, 20, 10, 15, 15, 10, 10, 10), 
  group = factor(c(rep("A", 3), rep("B", 3), rep("C", 3)), 
                 levels = c("A", "B", "C")))

# Plot 1
p <- ggplot(data1, aes(x = x, y = y, color = group, shape = group)) + 
  geom_line(show.legend = FALSE) +
  geom_point()
p

# Data 2
data2 <- data.frame(
  x = c(1, 2), 
  y = c(10, 19.3, 10, 12.5, 10, 7.5), 
  group = data1$group[-c(3, 6, 9)],
  condition = c("Y", "Z")
)

p +
  geom_line(data = data2, aes(x = x, y = y, color = group), 
            linetype = "dotted", show.legend = TRUE) +
  geom_point(data = data2)

Created on 2024-09-15 with reprex v2.1.1

And I'm trying to get this legend:

enter image description here

But without the linetype for the group legend, only the shape.


Solution

  • Before plotting, combine the data sets for each condition, using an id variable to track the source. Then you can map this new column to the linetype aesthetic, getting you most of the way towards the legend you describe. To remove the lines from the color legend you can override the aesthetics. linetype = 0 is a blank line.

    library(ggplot2)
    library(dplyr)
    
    data1 <- data.frame(
      x = c(1, 2, 3), 
      y = c(10, 20, 20, 10, 15, 15, 10, 10, 10), 
      group = factor(c(rep("A", 3), rep("B", 3), rep("C", 3)), 
                     levels = c("A", "B", "C")))
    
    data2 <- data.frame(
      x = c(1, 2), 
      y = c(10, 19.3, 10, 12.5, 10, 7.5), 
      group = data1$group[-c(3, 6, 9)]
    )
    
    bind_rows(data1, data2, .id = 'condition') |>
      ggplot(aes(x = x, y = y, color = group, shape = group, linetype = condition)) +
      geom_point() +
      geom_line() +
      guides(color = guide_legend(override.aes = list(linetype = 0)))
    

    an example plot generated with ggplot2 depicting the question's toy data with points and colored lines.