Search code examples
rggplot2colorslegend

Legend for ggplot2 with interaction of discrete and continuous variables


I have a general problem with plotting a good looking legend for the following data set.

df1 <- data.frame("ShearRate" = rep(c(1,5,10), rep(5,3)), "Time" = seq(1,15,1),
                 "Viscosity" = c(runif(5,15,20), runif(5,10,15), runif(5,5,10)),
                 "Test" = "Test1", "Interval" = rep(c("Interval1", "Interval2", "Interval3"),rep(5,3)))
df2 <- data.frame("ShearRate" = rep(c(1,5,10), rep(5,3)), "Time" = seq(1,15,1),
                 "Viscosity" = c(runif(5,15,20), runif(5,10,15), runif(5,5,10)),
                 "Test" = "Test2", "Interval" = rep(c("Interval1", "Interval2", "Interval3"),rep(5,3)))
df <- full_join(df1,df2)
rm(df1,df2)
df$Test <- as.factor(df$Test)
df$Interval <- as.factor(df$Interval)

Right now I am able to prodoce the following plot:

df %>%
  ggplot(aes(Time, Viscosity, col = interaction(Test,factor(ShearRate), sep="/Shear Rate [mPas]: ")))+
  theme_bw() +
  geom_smooth(show.legend = T) + 
  scale_colour_manual(values = c("red3", "blue3", "red2", "blue2", "red", "blue")) +
  geom_point(aes(shape = Interval)) +
  labs(x = "Time [s]", y = "Viscosity [mPas]", col = "Test ID")

which looks fine to me:

I needed to use the interaction of the variable Test with the variable ShearRateto achieve this plot. But I am really not satisfied with the legend it generates. Actually I would love to have a legend for the Test. Something like red: Test1 and blue: Test2. And a legend with a hue which gives us the intensity of continuous ShearRate

I hope my question is clear and that my MWE helps you to understand my problem.

Best regards!


Solution

  • I'm not quite sure what you mean by having a different hue for the values of ShearRate if you wish to specify the colors according to Test. I think you mean have a bluish gradient for ShearRate when Test == "Test2" and a reddish gradient when Test == "Test1". This isn't really possible natively in ggplot, but you can do it using ggnewscale:

    library(ggnewscale)
    
    ggplot(mapping = aes(Time, Viscosity)) +
      geom_line(data = df[df$Test == "Test1",],
                aes(color = ShearRate, group = factor(ShearRate)), 
                stat = "smooth", 
                show.legend = TRUE, size = 1) +
      geom_point(data = df[df$Test == "Test1",],
                 aes(shape = Interval, color = ShearRate)) +
      scale_color_gradient(low = "red4", high = "tomato", 
                           name = "Test1:\nShear rate") +
      ggnewscale::new_scale_color() +
      geom_line(data = df[df$Test == "Test2",],
                aes(color = ShearRate, group = factor(ShearRate)), 
                stat = "smooth", 
                show.legend = TRUE, size = 1) +
      geom_point(data = df[df$Test == "Test2",],
                 aes(shape = Interval, color = ShearRate)) +
      scale_color_gradient(low = "blue4", high = "deepskyblue", 
                           name = "Test2:\nShear rate") +
      labs(x = "Time [s]", y = "Viscosity [mPas]") +
      guides(alpha = guide_none(), shape = guide_none()) +
      theme_bw() +
      theme(legend.direction = "horizontal")
    

    enter image description here