how keep aesthetic mapping but remove a specific item from legend with ggplot

How would I go about modifying the following code to keep the graph as is, but remove the item 'c' from the legend?

library(tidyverse)
tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column))

Created on 2020-02-13 by the reprex package (v0.3.0)

Part of the goal is to keep the aesthetic mapping: scale_fill_manual() allows me to specify which items should appear in the legend, but at the same time seems to require that I specify the color values by hand.

Thanks,
David

FWIW, you can access the default colours for the discrete palette using scales::hue_pal(). The show_col() function I'm using below is just a convenience function for printing the colours for you to see:

scales::hue_pal()(3)
#> [1] "#F8766D" "#00BA38" "#619CFF"
scales::show_col(scales::hue_pal()(3))

Created on 2020-02-13 by the reprex package (v0.3.0.9001)

Specifying this directly in scale_fill_manual() gets rid of the fill for the bar as well, but you might be able to do a workaround with one of the guides() functions.

library(tidyverse)
tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column)) +
  scale_fill_manual(values = c(scales::hue_pal()(3)[[1]], scales::hue_pal()(3)[[2]], NA))

1 Like

Thank you, Mara -- this is very helpful! I didn't know it was possible to access the discrete palette directly.

Using your suggestion, here a modification that uses the limits argument) and does the job:

library(tidyverse)

my_colors <- scales::hue_pal()(3)
# add names so bar for 'c' gets fill, too
names(my_colors) <- letters[1:3] 

tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column)) +
  scale_fill_manual(
    values = my_colors,
    limits = c('a', 'b')
    )

Created on 2020-02-13 by the reprex package (v0.3.0)

2 Likes

:tada:Great work! I could've sworn I gave that one a go, but it's all a haze of function mishmash now!

Yikes! Update, this behaviour has changed in the development version such that the column is filtered out. I'll file an issue to make sure this is intended.

library(tidyverse)

my_colors <- scales::hue_pal()(3)
# add names so bar for 'c' gets fill, too
names(my_colors) <- letters[1:3] 

tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column)) +
  scale_fill_manual(
    values = my_colors,
    limits = c('a', 'b')
  )

Created on 2020-02-13 by the reprex package (v0.3.0.9001)

This was an intended change. See the implementation PR for how it will work in subsequent releases:

Thanks for the heads up, Mara, and for pointing to where I can dig further. I was able to achieve the same effect by replacing limits by breaks -- does that change anything for you? In looking through the current version of Hadley Wickham's ggplot2 book online, it seems that breaks may have been intended for this kind of tuning:

library(tidyverse)
my_colors <- scales::hue_pal()(3)

# add names so bar for 'c' gets fill, too
names(my_colors) <- letters[1:3]

tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column)) +
  scale_fill_manual(
    values = my_colors,
    breaks = c('a', 'b')
    )

Created on 2020-02-14 by the reprex package (v0.3.0)

1 Like

@mara: Oh and it looks like the breaks argument lets me use scale_fill_discrete() without having to specify the colors:

library(tidyverse)

tibble(column = letters[1:3]) %>% 
  ggplot(aes(column)) +
  geom_bar(aes(fill = column)) +
  scale_fill_discrete(breaks = c('a', 'b'))

Created on 2020-02-14 by the reprex package (v0.3.0)

1 Like

Sweet! Nailed it. Works with dev now, too!

1 Like

Thanks for all your help!

1 Like

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