Home > Mobile >  How fill geom_ribbon with different colour in R?
How fill geom_ribbon with different colour in R?

Time:11-25

I am trying to use different fill for geom_ribbon according to the x-values (For Temp = 0-20 one fill, 20-30.1 another fill and > 30.1 another fill). I am using the following code

library(tidyverse)

bounds2 <- df %>% 
  mutate(ymax = pmax(Growth.rate, slope),
         ymin = pmin(Growth.rate, slope),
         x_bins = cut(Temp, breaks = c(0,20,30.1,max(Temp) 5)))

ggplot(df, aes(x = Temp, y = Growth.rate))  
  geom_line(colour = "blue")  
  geom_line(aes(y = slope), colour = "red")  
  scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope"))  
  geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = x_bins), 
              alpha = 0.4)

It is returning me following output enter image description here

As you can see from the output some regions are remaining empty. Now how can I fill those parts in the curve? Here is the data

df = structure(list(Temp = c(10, 13, 17, 20, 25, 28, 30, 32, 35, 38
), Growth.rate = c(0, 0.02, 0.19, 0.39, 0.79, 0.96, 1, 0.95, 
0.65, 0), slope = c(0, 0.02, 0.16, 0.2, 0.39, 0.1, 0.03, -0.04, 
-0.29, -0.65)), row.names = c(NA, 10L), class = "data.frame")

CodePudding user response:

Here's a solution that involves interpolating new points at the boundaries between the areas. I used approx to get the values of ymin and ymax at Temp=30.1 and added this to the plotting dataset.

Then, instead of using cut just once as you did I use it twice, once with lower bounds included in each set then once with upper bounds included. Then I reshape the data long, and de-duplicate the rows I don't need.

If you zoom in enough you can see that the boundary is at 30.1 not at 30.

bounds2 <- df %>% 
  mutate(ymax = pmax(Growth.rate, slope),
         ymin = pmin(Growth.rate, slope))
bounds2 <- bounds2 |> 
  add_case(Temp=30.1, 
           ymax=approx(bounds2$Temp,bounds2$ymax,xout = 30.1)$y,
           ymin=approx(bounds2$Temp,bounds2$ymin,xout = 30.1)$y) |>
  mutate(x_bins2 = cut(Temp, breaks = c(0,20,30.1,max(Temp) 5),right=FALSE, labels=c("0-20","20-30.1","30.1-max")),
         x_bins =  cut(Temp, breaks = c(0,20,30.1,max(Temp) 5), labels=c("0-20","20-30.1","30.1-max"))) |> 
  tidyr::pivot_longer(cols=c(x_bins2, x_bins), names_to = NULL, values_to = "xb") |> 
  distinct()

ggplot(df, aes(x = Temp, y = Growth.rate))  
  geom_line(colour = "blue")  
  geom_line(aes(y = slope), colour = "red")  
  scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope"))  
  geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = xb), 
              alpha = 0.4)

enter image description here

CodePudding user response:

The idea is here but the code I show can be much improved at the step ### Dupplicate the 2 last x_bins from each category and move them into the next

### Libraries
library(tidyverse)

df <- structure(list(Temp = c(10, 13, 17, 20, 25, 28, 30, 32, 35, 38
), Growth.rate = c(0, 0.02, 0.19, 0.39, 0.79, 0.96, 1, 0.95, 
                   0.65, 0), slope = c(0, 0.02, 0.16, 0.2, 0.39, 0.1, 0.03, -0.04, 
                                       -0.29, -0.65)), row.names = c(NA, 10L), class = "data.frame")

### Preprocessing
bounds2 <- df %>% 
  mutate(ymax = pmax(Growth.rate, slope),
         ymin = pmin(Growth.rate, slope),
         x_bins = cut(Temp, breaks = c(0, 20, 30.1, max(Temp) 5)))

### Dupplicate the 2 last x_bins from each category and move them into the next category
bounds2 <- rbind(bounds2, bounds2[c(4, 7), ])
bounds2$x_bins[c(11, 12)] <- bounds2[c(5, 8), ]$x_bins

### Plot
ggplot(df, aes(x = Temp, y = Growth.rate))  
  geom_line(colour = "blue")  
  geom_line(aes(y = slope), colour = "red")  
  scale_y_continuous(sec.axis = sec_axis(~ .^1, name = "slope"))  
  geom_ribbon(data = bounds2, aes(Temp, ymin = ymin, ymax = ymax, fill = x_bins), 
              alpha = 0.4)

enter image description here

  • Related