rggplot2ggnewscale

ggplot melted data sharing common aesthetics


I need to plot a graph from a melted data.table that mixes three geoms: geom_line, geom_col and geom_point. geom_line and geom_point share a the color aesthetics:

set.seed(1)
time <- 1:10
mag  <- 10:20
q_mag <- c("up", "up", "down")
l_a  <- sample(1:12, 10)
l_b  <- sample(8:20, 10)
p_a  <- sample(1:12, 10)
p_b  <- sample(8:20, 10)

dt <- data.table(time, mag, q_mag, l_a, l_b, p_a, p_b)
dt <- melt(dt, measure.vars = c("mag", "l_a", "l_b", "p_a", "p_b"))


ggplot(data = dt, aes (x = time)) +
  geom_col( data = dt[variable %in% "mag"]
          , aes( y    = value
               , fill = q_mag)) +
  
  scale_fill_grey(start = .4) +
  
  geom_line( data = dt[variable %in% c("l_a", "l_b")]
            ,aes( y = value
                , color = variable)
            ,size =1) +
  
  geom_point( data = dt[variable %in% c("p_a", "p_b")]
             ,aes( y = value
                  ,color = variable
                  ,size = variable
                  ,shape = variable)) +

  scale_shape_manual( name = element_blank() 
                    , labels = c("Point A", "Point B")
                    , values = c("circle", "cross")
  )+    
  
  scale_size_manual( name = element_blank() 
                   , labels = c("Point A", "Point B")
                   , values = c(4,2)
  )+    
  
  scale_color_manual( name = element_blank()
                    , labels = c("Line A", "Line B", "Point A", "Point B")
                    , values = c("red", "green", "red", "blue")
  )

This code plots the graph as expected: enter image description here

However, I would like to have the legend presented in another way:

How do I accomplish the desired legend?


Solution

  • This could be easily achieved via the ggnewscale package which allows for multiple color scales:

    library(ggplot2)
    library(data.table)
    library(reshape2)
    library(ggnewscale)
    
    set.seed(1)
    time <- 1:10
    mag <- 10:20
    q_mag <- c("up", "up", "down")
    l_a <- sample(1:12, 10)
    l_b <- sample(8:20, 10)
    p_a <- sample(1:12, 10)
    p_b <- sample(8:20, 10)
    
    dt <- data.table(time, mag, q_mag, l_a, l_b, p_a, p_b)
    dt <- melt(dt, measure.vars = c("mag", "l_a", "l_b", "p_a", "p_b"))
    
    dt <- as.data.table(dt)
    
    ggplot(data = dt, aes(x = time, y = value)) +
      geom_col(
        data = dt[variable %in% "mag"],
        aes(
          fill = q_mag
        )
      ) +
      geom_point(
        data = dt[variable %in% c("p_a", "p_b")],
        aes(
          color = variable,
          size = variable,
          shape = variable
        )
      ) +
      scale_fill_grey(start = .4) +
      scale_shape_manual(
        name = element_blank(),
        labels = c("Point A", "Point B"),
        values = c("circle", "cross")
      ) +
      scale_size_manual(
        name = element_blank(),
        labels = c("Point A", "Point B"),
        values = c(4, 2)
      ) +
      scale_color_manual(
        name = element_blank(),
        labels = c("Point A", "Point B"),
        values = c("red", "blue")
      ) + 
      new_scale_color() +
      geom_line(
        data = dt[variable %in% c("l_a", "l_b")],
        aes(
          color = variable
        ), size = 1
      ) +
      scale_color_manual(
        name = element_blank(),
        labels = c("Line A", "Line B"),
        values = c("red", "green")
      )