Home > Software engineering >  Custom labels for limit and break values when using scale_color_binned in r ggplot
Custom labels for limit and break values when using scale_color_binned in r ggplot

Time:04-24

I want to display a discrete scale with custom labels for break points and include limits with custom labels. I am aware of code that works when showing breaks within limits, but when limits are active, labeling no longer works with this method

Here is the method that works:

library(ggplot2)

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c(1999, 2008),
                    breaks = c(2000, 2002, 2004, 2006),
                    labels = c('2', '3', '4', '5'),
                    show.limits = F) # proof that this method works for breaks WITHIN limits

When limits are activated for this plot, ggplot gives an error message and does not render the plot

library(ggplot2)

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c(1999, 2008),
                    breaks = c(2000, 2002, 2004, 2006),
                    labels = c('2', '3', '4', '5'),
                    show.limits = T) # method fails when limits are activated

Error in f(): ! Breaks and labels are different lengths

Breaks and labels are obviously the same length. Perhaps something about activating limits changes how the label vector is formed? I know where to find code for the ggplot2 break vector (using ggplot_build() or clicking directly on a saved plot object). I looked through those and found nothing that helped me understand how to resolve this issue.

I also tried these methods and it returned the same error 'breaks and labels are different lengths':

# this did not work

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c(1999, 2008),
                    breaks = c(2000, 2002, 2004, 2006),
                    labels = c('1', '2', '3', '4', '5', '6')
                    show.limits = T) # added more entries to label vector did not work

# this also did not work

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_x_continuous(
    breaks = c(0, 20, 40),
    labels = c("0", "20", "40"))    
  scale_color_binned(breaks = c(1999, 2000, 2002, 2004, 2006, 2008),
                     labels = c('1', '2', '3', '4', '5', '6'),
                     show.limits = F) # add limits directly to breaks did not work

One method that could be used to label each entry is written below. However, this method is tedious if there are several entries for the discrete scale.

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c('1' = 1999, '6' = 2008),
                    breaks = c('2' = 2000, '3' = 2002, '4' = 2004, '5' = 2006),
                    show.limits = T) # this works, but is a tedious solution when writing several breaks

I want to use the scale_color_binned method (or similar functions) because I want to convert continuous scale data to 15-20 discrete ranges and then custom label or suppress labels for different ranges.

Is there a way to generate a ggplot that can accept custom labels for binned continuous values while also showing specified limits for the data?

CodePudding user response:

You get an idea of what's going on if you use a function to label the breaks:

library(ggplot2)

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c(1999, 2008),
                    breaks = c(2000, 2002, 2004, 2006),
                    labels = ~ print(.x),
                    show.limits = TRUE)
#> [1] 2000 2002 2004 2006
#> [1] 1999 2008

You can see that the labels for breaks and for limits are sent in two separate batches to the labelling function, so a fixed-length vector of labels is always going to fail for one or other of these batches. Really, you need a function that can handle either:

ggplot(mpg, aes(cty, hwy, color = year))  
  geom_point()  
  scale_color_binned(limits = c(1999, 2008),
                    breaks = c(2000, 2002, 2004, 2006),
                    labels = ~ if(length(.x) == 2) .x else 1:4,
                    show.limits = TRUE)

enter image description here

  • Related