rggplot2geom-ribbon

Control colours on double geom_ribbon for two variables with ggplot2 in R


I want to show two ribbons per variable e.g. (max - min ribbon, and a confidence level ribbon) with geom_ribbon() in ggplot2 in R, as in the example below. I've not been able to set the colours for each ribbon separately. Ideally, I can map a colour palette to each level of the categorical variable (type), and the two ribbons will take colours from these.

## Set up data
set.seed(999)
n <- 100

mn1 <- seq(0.5, 0.9, length.out = n)
mn2 <- seq(0.75, 0.25, length.out = n)

tmp1 <- lapply(seq_len(n), function(x) {
  
  x1 <- rnorm(n, mn1[x], 0.1)
  x2 <- rnorm(n, mn2[x], 0.1)
  
  rbind(cbind(min(x1), mean(x1)-sd(x1), mean(x1), mean(x1)+sd(x1), max(x1)),
        cbind(min(x2), mean(x2)-sd(x2), mean(x2), mean(x2)+sd(x2), max(x2))
  )
})

year <- seq(1900, 1900+n-1, 1)
type <- rep(c("all", "partial"), n)

df1 <- data.frame(rep(year,each = 2), do.call(rbind, tmp1), type)
colnames(df1) <- c("year", "xmin", "xsd_lwr", "xmn", "xsd_upr", "xmax", "type")
head(df1)                  
rm(tmp1, mn1, mn2, year, type, n)

This is what I have so far in ggplot2:

library(ggplot2)

ggplot(df1, aes(x = year, y = xmn, fill = type, col= type))+
  geom_ribbon(aes(ymin=xsd_lwr, ymax = xsd_upr), linetype = 0, alpha = 0.4)+
  geom_ribbon(aes(ymin=xmin, ymax = xmax), linetype = 0, alpha = 0.4)+
  scale_color_manual(values = c("black", "darkred"))+
  scale_fill_manual(values = c("grey10", "grey30"))+
  geom_line(aes(linetype= type), size = 1)+
  scale_x_continuous(breaks = seq(1900, 2000,10))

Double ribbon ggplot geom_ribbon

UPDATE: I've accepted the answer as it does give exact control for four different colours, however, I wanted to show that the comment by @teunbrand also works as the transparency, in effect, creates four colours too, and has a better legend. I've modified the suggestion to this below:

ggplot(df1, aes(x = year, y = xmn,col= type))+
  geom_ribbon(aes(ymin=xsd_lwr, ymax = xsd_upr, fill = type), linetype = 0, alpha = 0.5)+
  geom_ribbon(aes(ymin=xmin, ymax = xmax, fill = type), linetype = 0, alpha =0.5)+
  scale_fill_manual(values = c("tomato", "dodgerblue"))+
  scale_color_manual(values = c("black", "darkred"))+
  geom_line(aes(linetype= type), size = 1)+
  scale_x_continuous(breaks = seq(1900, 2000,10))

enter image description here


Solution

  • You could define a specific fill group in the ribbon's aes, and associate the color you wish with it in scale_fill_manual:

    ggplot(df1, aes(x = year, y = xmn, fill = type, col= type))+
      geom_ribbon(aes(ymin=xsd_lwr, ymax = xsd_upr), linetype = 0, alpha = 0.4,show.legend=F)+
      scale_fill_manual(values = c("grey10","red","grey30","green"))+
      geom_ribbon(aes(ymin=xmin, ymax = xmax,fill=ifelse(type=='all','all_minmax','partial_min_max')), linetype = 0, alpha = 0.4,show.legend=F)+
      scale_color_manual(values = c("black", "darkred"))+
      geom_line(aes(linetype= type), size = 1)+
      scale_x_continuous(breaks = seq(1900, 2000,10))
    

    Note that I had to remove the legend for the ribbons to avoid to show the second legend with the new color groups. enter image description here