Search code examples
rggplot2legendfill

ggplot scale_fill_identity legend missing when specifying labels and breaks


I have data like this, where I want to specify my fill color within the data frame (color column). I want my legend to show the values in the cut_value column. When I specify both labels and breaks, the legend disappears. The legend does show if I only include labels, and not breaks. However, I need to specify the breaks, as I need them consistent across multiple plots where the data include different data ranges for cut_value. How do I include labels and breaks and have the fill legend show?

library(tidyverse)

df <- data.frame(sample = letters[1:6],
                 value = c(1,1.5,NA,3,4, 2)) %>% 
  mutate(cut_value = cut(value, breaks = c(1,2,3,4)),
         color = factor(cut_value, 
                        levels = levels(cut_value),
                        labels = c('darkred', 'orange', 'yellow')),
         color = fct_explicit_na(color, na_level = 'grey85'))

ggplot(df, aes(sample, value))+
  geom_bar(stat = 'identity', aes(fill = color))+
  scale_fill_identity(guide = 'legend',
                      labels = levels(df$cut_value))
                      breaks = levels(df$cut_value))

Solution

  • In breaks you need to specify which levels of color to show, rather than which levels of cut_value. Here I drop the grey85 level using levels(df$color)[-4].

    ggplot(df, aes(sample, value))+
      geom_bar(stat = 'identity', aes(fill = color))+
      scale_fill_identity(guide = 'legend',
                          labels = levels(df$cut_value),
                          breaks = levels(df$color)[-4])
    

    enter image description here


    EDIT: if you have multiple datasets with different ranges for cut_value you can drop the grey85 level by name rather than by position.

    breaks = levels(df$color)[levels(df$color) != 'grey85']