Separate Legend Entries for Individual Outlined Overlapping Bars

38 Views Asked by At

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

2

There are 2 best solutions below

0
zephryl On BEST ANSWER

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"))

0
M-- On

Just for laffs; this has the benefit of showing both lines where old and mat bars collide, but complicates things beyond what OP seems to be asking for.

library(ggplot2)
library(dplyr)
library(tidyr)

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

d %>% 
  mutate(fmlb = fmlb - old - mat) %>% 
  pivot_longer(-grp) -> d1

ggplot(data = d1, 
       aes(x = grp, y = value, fill = grp, color = name)) +
  geom_bar(stat = "identity", 
           linewidth = ifelse(d1[["name"]] == "fmlb", 0, 1)) +
  geom_errorbar(data = d, 
                aes(y=old,ymin=old,ymax=old), colour="black") +
  scale_color_manual(name = "Legendary", 
                     values = c("mat" = "green", "old" = "black"), 
                     guide = guide_legend(order = 2),
                     labels = c("Mature", "Old")) +
  guides(color=guide_legend(override.aes=list(fill=NA))) +
  ylab("fmlb")

Created on 2024-03-26 with reprex v2.0.2