Home > database >  How to predefine legend colours based on value range using ggplot2 and RColorBrewer?
How to predefine legend colours based on value range using ggplot2 and RColorBrewer?

Time:03-15

I have some data from a range of tests that I'm calculating STEN scores for. I'm aiming to visualise this data in the form of a circular bar plot and would like to set the colour gradient based on a STEN score range. For example, a score of 0-2 would be a very light colour, 2.1-4 light, 4.1-6 moderate, 6.1-8 dark and 8.1-10 very dark. My code below uses the RColorBrewer package and the "YlGn" palette, but I'm stuck on how I can predefine the colour scheme based on the example mentioned above and set this in the plot legend. The example below produces a circular bar plot containing a lowest STEN score of 4.8, so I would like this to be reflected as the moderate colour, where currently its the lightest. I essentially want the legend to show all five STEN score ranges irrespective of whether someone's data scores within each range. Hope this makes sense.

library(tidyverse)
library(RColorBrewer)

set.seed(50)
dat <- data.frame(
  
  par = paste("par", 1:15),
  test_1 = round(rnorm(15, mean = 30, sd = 5), 1),
  test_2 = round(rnorm(15, mean = 30, sd = 5), 1),
  test_3 = round_any(rnorm(15, mean = 90, sd = 5), 2.5),
  test_4 = round(rnorm(15, mean = 5.4, sd = 0.3), 1),
  test_5 = round(rnorm(15, mean = 17, sd = 1.5), 1)
  
)

sten_dat <- dat %>%
  mutate_if(is.numeric, scale) %>%
  mutate(across(c(2:6), ~ . * 2   5.5)) %>%
  mutate(across(where(is.numeric), round, 1)) %>%
  pivot_longer(!par, names_to = "test", values_to = "sten") %>%
  filter(par == "par 1")

ggplot(sten_dat)  
  geom_col(aes(x = str_wrap(test), y = sten, fill = sten),
           position = "dodge2", alpha = 0.7, show.legend = TRUE)  
  coord_polar()  
  scale_y_continuous(limits = c(-1, 11), breaks = seq(0, 10, 2))  
  scale_fill_gradientn(colours = brewer.pal(name = "YlGn", n = 5))`

CodePudding user response:

Simply add limits to your fill scale:

ggplot(sten_dat)  
  geom_col(aes(x = str_wrap(test), y = sten, fill = sten),
           position = "dodge2", alpha = 0.7, show.legend = TRUE)  
  coord_polar()  
  scale_y_continuous(limits = c(-1, 11), breaks = seq(0, 10, 2))  
  scale_fill_gradientn(colours = brewer.pal(name = "YlGn", n = 5),
                       limits = c(0, 10))

enter image description here

If you want the colors to be clearly "binned" in the way you describe, you can use scale_fill_stepn instead of scale_fill_gradientn

ggplot(sten_dat)  
  geom_col(aes(x = str_wrap(test), y = sten, fill = sten),
           position = "dodge2", alpha = 0.7, show.legend = TRUE)  
  scale_y_continuous(limits = c(-1, 11), breaks = seq(0, 10, 2))  
  scale_fill_stepsn(colours = brewer.pal(name = "YlGn", n = 5),
                    limits = c(0, 10), breaks = 0:5 * 2)  
  geomtextpath::coord_curvedpolar()  
  theme_minimal()  
  theme(axis.text.x = element_text(size = 16, face = 2),
        panel.grid.major.x = element_blank())

enter image description here

  • Related