suprising behavior of ggplot's show.legend=F ?

Why are the two plots below not identical? By setting show.legend=F in geom_bar I would expect the related legends (pertaining to the defined aesthetics) not to show up, irrespective of whether I set show.legend to NA or TRUE in another geom. I am aware that I can specify legends also via guides. But I am puzzled by show.legends behavior and would like to understand it better. Thx!

library(tidyverse)

my_df <- tibble(my_dates=seq.Date(from=as.Date("2019/01/01"),
                                          to=as.Date("2019/01/10"),
                                          by="day"),
                my_values=seq(1:10),
                my_groups=rep(c("a","b"), each=5))

my_indicators <- c("2019/01/05", "2019/01/09") %>% 
  enframe(., name="indicator_id", value="indicator_dates") %>% 
  mutate_at(vars(contains("dates")), as.Date) %>% 
  mutate_at(vars(contains("id")), as.character) 

my_df %>% 
  ggplot()+
  geom_bar(aes(x=my_dates, 
               y=my_values,
               fill=my_groups),
           stat="identity",
           show.legend = F)+
  geom_vline(data=my_indicators,
             aes(xintercept=indicator_dates,
                 color=indicator_id),
             show.legend=T)

  
my_df %>% 
  ggplot()+
  geom_bar(aes(x=my_dates, 
               y=my_values,
               fill=my_groups),
           stat="identity",
           show.legend = F)+
  geom_vline(data=my_indicators,
             aes(xintercept=indicator_dates,
                 color=indicator_id),
             show.legend = NA)

Created on 2019-09-18 by the reprex package (v0.3.0)

1 Like

This behaviour is borderline a bug, but it comes from a good place :slightly_smiling_face:. Setting show.legend = TRUE will force the layer to participate in all guides, even the ones it doesn't add anything to. This means that geom_vline() will take part in the fill guide. In the second example the fill guide is not turned off by setting show.legend = FALSE in geom_bar, it is just not shown because no layer contribute to it. In the first example it is shown because we force geom_vline() to contribute to it, but since fill is not mapped in this geom (obviously) we simply grab the default aesthetics and draw it with the draw_key function from geom_vline().

In general, show.legend = TRUE is a danger zone of unexpected side effects - especially when combined with show.legend = FALSE in other layers.

3 Likes

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.