rggplot2scalegradientfill

How to put a scale gradient with specific values to ggplot geom_bar?


I would like to create a barplot with ggplot2 puttingg a scale fill gradient where I can set the values of min, mid and max (in my case it would be: min = 0, mid = 50, max = 100). For each of these values I'd like to associate a scale gradient where 0 correspond to blue, mid to yellow (or white) and 100 to red.

I found nothing here, could you help me please?

Thank you in advance.

Here there is the code I tried to use but didn't work (the barplot I obtain has has gray bars).

TPH <- ggplot(ser, aes(x= Stages, y= TPH))+
  geom_bar(stat = "identity")+
  scale_fill_gradient(low='blue', high='red')+
  labs(y= expression("Counts per million (CPM)"), x = "Hours post fertilization (hpf)")+
  ggtitle("Tryptophan Hydroxylase", subtitle = "TPH")+
  theme(plot.title=element_text(hjust=0.5),
        plot.subtitle=element_text(hjust=0.5))+
  scale_y_continuous(limits=c(0, 100))+
  scale_x_discrete(labels=c("hpf00" = "0", "hpf04" = "4", "hpf08" ="8", "hpf12"="12", "hpf16"="16", "hpf20"="20","hpf24"="24", "hpf28"="28", "hpf32"="32", "hpf36"="36","hpf40"="40", "hpf44"="44", "hpf48"="48", "hpf52"="52", "hpf72"="72"))
TPH 

Solution

  • Assuming that your data looks like this (please include some example data in your next questions)

    # libraries
    library(tidyr)
    library(dplyr)
    library(ggplot2)
    
    # set seed for reproducibility
    set.seed(123) 
    
    # get example data
    ser <- data.frame(Stages = c("hpf00", "hpf04", "hpf08", "hpf12", "hpf16",
                                     "hpf20", "hpf24", "hpf28", "hpf32", "hpf36",
                                     "hpf40", "hpf44", "hpf48", "hpf52", "hpf72")) %>%
          mutate(TPH = sample(1:100, length(Stages)))
    

    you can generate a vector from 0 to your observation per level of Stages (following the answer provided here https://stackoverflow.com/a/71043558/15024678). You then unnest these vectors:

    ser_mod <- ser %>%
      mutate(TPH = purrr::map(TPH, ~0:.x)) %>%
      unnest_longer(TPH)
    

    This can be plotted using geom_tile() resulting in a bar chart that fits your description.

    ggplot(ser_mod, aes(x = Stages, y = TPH)) +
      geom_tile(aes(fill = TPH, width = .9)) +
      scale_fill_distiller(palette = "RdYlBu") +
      theme(legend.position = "none")
    

    Output: enter image description here

    Modified solution if you want to have the bar completely in red if the maximum value per level on the x-axis is 100

    Get modified example data so that TPH = 100 for hpf12:

    # set seed for reproducibility
    set.seed(123) 
    
    # get example data
    ser <- data.frame(Stages = c("hpf00", "hpf04", "hpf08", "hpf12", "hpf16",
                                 "hpf20", "hpf24", "hpf28", "hpf32", "hpf36",
                                 "hpf40", "hpf44", "hpf48", "hpf52", "hpf72")) %>%
      mutate(TPH = sample(1:100, length(Stages))) %>%
      mutate(TPH = ifelse(Stages == "hpf12", 100, TPH))
    

    After generating the column containing values from 0 to the value of your observation per level of TPH you can generate a new column (TPH_fill) you use for coloring. This column can then be modified so that it only contains 100 (resulting in red color) if the maximum value of TPH is 100:

    ser_mod <- ser %>%
      mutate(TPH = purrr::map(TPH, ~0:.x)) %>%
      unnest_longer(TPH) %>%
      group_by(Stages) %>%
      mutate(TPH_fill = ifelse(max(TPH) == 100, 100, TPH)) %>%
      mutate(TPH_fill = ifelse(TPH_fill != 100, TPH, TPH_fill))
    

    Plot using TPH_fill as argument for fill:

    ggplot(ser_mod, aes(x = Stages, y = TPH)) +
      geom_tile(aes(fill = TPH_fill, width = .9)) +
      scale_fill_distiller(palette = "RdYlBu") +
      theme(legend.position = "none")
    

    Output: enter image description here

    Modified solution if you do not want to have the color gradient along the y axis but bars colored by their maximum value

    You can plot a geom_col() based on the unmodified data and set fill by the value of TPH:

    ggplot(ser, aes(x = Stages, y = TPH)) +
      geom_col(aes(fill = TPH)) +
      scale_fill_distiller(palette = "RdYlBu") +
      theme(legend.position = "none")
    

    Output: enter image description here