'How can I add a legend for error bars in ggplot?

I have been trying to amend what I thought was a straightforward legend on my GGPlot for a day now and not making much progress (I have searched extensively on Stackexchange and can't see an obvious parallel).

Put simply: I am showing a revenue vs forecast bar chart where horizontal lines represent the forecast. I've managed to get the horizontal bars with a zero-width error bar. The columns are captured in the legend, but I can't figure out how to add a legend for the error bars:

enter image description here

Here is a reproducible example. I've added the full aesthetic settings I need in my final image, in case they are causing some clash I am missing:

df = data.frame(Team=c("Dunder Mifflin","Saber","Wernham Hogg",
                       "OsCorp","Queen Industries","Stark Industries"),
                Industry=c("Paper","Paper","Paper",
                           "Tech","Tech","Tech"),
                Revenue=c(20,100,10,
                          50,150,200),
                Forecast=c(30,120,5,
                           70,120,120))

g1 = ggplot(df) + 
  geom_col(aes(x=Team,y = Revenue,fill=Industry)) +
  geom_errorbar(aes(x=Team,y=Forecast, ymax=Forecast, ymin=Forecast)) +
  # Everything from here probably irrelevant aesthetic settings,
  # included in case there is some clash I am unaware of
  scale_fill_hue(c = 40) + 
  facet_grid(cols = vars(Industry),
             scales = "free_x",
             space = "free_x",
             switch="x") +
  theme_bw() + 
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        axis.line = element_line(),
        strip.placement = "outside",
        strip.text.x = element_text(size=10),
        strip.background.x = element_rect(colour = "grey", fill = "white"),
        text=element_text(family="Roboto",face="bold"))

print(g1)


Solution 1:[1]

Try this trick. You can use geom_line(), pass a zero value and adding the option color='forecast'. That will create a legend similar to that expected. Here the code:

library(ggplot2)
#Plot
ggplot(df) + 
  geom_col(aes(x=Team,y = Revenue,fill=Industry)) +
  geom_line(aes(x=Team,y=0,color='forecast',group=1))+
  geom_errorbar(aes(x=Team,y=Forecast, ymax=Forecast, ymin=Forecast)) +
  # Everything from here probably irrelevant aesthetic settings,
  # included in case there is some clash I am unaware of
  scale_fill_hue(c = 40) +
  scale_color_manual(values='black')+
  facet_grid(cols = vars(Industry),
             scales = "free_x",
             space = "free_x",
             switch="x") +
  theme_bw() + 
  theme(panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        axis.line = element_line(),
        strip.placement = "outside",
        strip.text.x = element_text(size=10),
        strip.background.x = element_rect(colour = "grey", fill = "white"),
        text=element_text(family="Roboto",face="bold"))+
  labs(color='')

Output:

enter image description here

Solution 2:[2]

You could use coord_cartesian to limit the axes and change the line so that it's below y=0, so something like this:

ggplot(df) + 
geom_col(aes(x=Team,y = Revenue,fill=Industry)) +
geom_line(aes(x=Team,y=-10,color='forecast',group=1))+
geom_errorbar(aes(x=Team,y=Forecast, ymax=Forecast, ymin=Forecast)) +
scale_fill_hue(c = 40) +
scale_color_manual(values='black')+
facet_grid(cols = vars(Industry),
         scales = "free_x",
         space = "free_x",
         switch="x") +
theme_bw() + 
theme(panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    axis.line = element_line(),
    strip.placement = "outside",
    strip.text.x = element_text(size=10),
    strip.background.x = element_rect(colour = "grey", fill = "white"),
    text=element_text(family="Roboto",face="bold"))+
labs(color='')+
coord_cartesian(ylim=c(0,200))
#assuming 200 is your ymax

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 strugglebus