Search code examples
rggplot2bar-chartlegend

Separate Legend Entries for Individual Outlined Overlapping Bars


I am creating a ggplot with multiple overlapping bar plots. The first underlying bar is filled with color and then I overlay one more set of bars with just an outline to show sub-components. I would like to have each of these bars show up in the legend but I cannot figure out how to do it. I would like a separate legend entry for the Black outline bar and the Green outlined bar.

d <- data.frame(grp=c('a','b','c'), 
                fmlb=c(100,115,125), 
                old=c(20,35,15), 
                mat=c(10,15,5))

p <-  ggplot() +
    geom_col(data=d,
             aes(x=grp, y=fmlb, fill=grp), stat="identity") +
    geom_col(data=d, 
             aes(x=grp,y=mat), 
             alpha=0, size=0.5, colour="green", 
            stat="identity", position=position_nudge(y=d$old)) +
    geom_col(data=d, 
             aes(x=grp,y=old), alpha=0, size=0.5, colour="black", 
             position="dodge") + 
    scale_color_manual(name="Legendary", 
                       values = c("Old" = "black", "Mature" = "green"), 
                        guide = guide_legend(order = 2))

What the Chart Currently Looks Like


Solution

  • Pivot your "Legendary" columns to long format and map to color. This also handles the positioning such that you don't have to include position_nudge(y=d$old).

    library(dplyr)
    library(tidyr)
    library(ggplot2)
    
    d_part_long <- d %>% 
      select(grp, Old = old, Mature = mat) %>% 
      pivot_longer(Old:Mature, names_to = "Legendary") %>% 
      # arrange to plot black outline over green outline as in example
      arrange(Legendary)
    
    ggplot() +
      geom_col(data = d, aes(grp, fmlb, fill = grp)) +
      geom_col(data = d_part_long, aes(grp, value, color = Legendary), alpha = 0) +
      scale_color_manual(values = c("Old" = "black", "Mature" = "green"))