rggplot2curveviolin-plot

R display a violin plot over curve


I would like to draw on the same plot a curve and some violin plots. Is it possible ? For now, I'm only able to draw them separately, one of the top of the other as in the example code.

Here is an example code (with trim=TRUE the alignment is better, but I would like to keep trim=FALSE)

library("ggpubr")
library("ggplot2")
temps <- data.frame("LvlTemp"= c(rep("low", 10), 
                                 rep("medium", 15), 
                                 rep("high", 20)),
                    "Value" = c(runif(10, 0, 30), runif(15, 5, 40),runif(20, 15, 40) ))

df_E_old <- data.frame("Temp"=0:40, "dE_old"=sqrt(0:40))

Vplot <- ggplot(temps, aes(x = LvlTemp, y = Value, fill=LvlTemp, color=LvlTemp, alpha=0.5, 
                                ymin=0, ymax = 40)) +
  geom_violin(trim=FALSE) +
  coord_flip() + # This switch X and Y axis and allows to get the horizontal version
  xlab("") +
  ylab("Temperature (°C)") +
  theme(
    legend.position="none" # no legend, don't know yet
  ) +
  scale_x_discrete(limits=c("low", "medium", "high")) +
  scale_color_manual(values=c("red", "blue", "purple"))+
  scale_fill_manual(values=c("red", "blue", "purple")) 

Lplot <- ggplot(df_E_old, aes(x=Temp, y=dE_old)) + 
  geom_line() 


ggarrange(Vplot, Lplot,
          ncol = 1, nrow = 2, align="v")

Here is an idea of what I want to obtain enter image description here

EDIT : I succeed thanks to the example of liaifat85

library("ggpubr")
library("ggplot2")
temps <- data.frame("LvlTemp"= c(rep("low", 10), 
                                 rep("medium", 15), 
                                 rep("high", 20)),
                    "Value" = c(runif(10, 0, 30), runif(15, 5, 40),runif(20, 15, 40) ))

df_E_old <- data.frame("Temp"=0:40, "dE_old"=sqrt(0:40))

temps$LvlTemp <- factor(temps$LvlTemp, levels = c("low", "medium", "high"))

diviseur <- 1

ggplot() +
  geom_path(data = df_E_old, aes(x = dE_old, y = Temp), color = "black", linewidth = 1) +
  geom_violin(data = temps, aes(x = as.numeric(LvlTemp)/diviseur, y = Value, 
                                fill = LvlTemp, color = LvlTemp), 
              alpha = 0.5, trim = TRUE) +
  coord_flip() + # This switch X and Y axis and allows to get the horizontal version
  # Add labels and theming
  xlab("Development rate") +
  ylab("Temperature (°C)") +
  theme_minimal() +
  theme(legend.position = "none") +
  scale_color_manual(values = c("blue", "purple", "red")) +
  scale_fill_manual(values = c("blue", "purple", "red"))

I still have to do some work about diviseur or something else to automatically have the right range depending on the values of the curve


Solution

  • It seems you just need to create the x-axis (y-axis after coord flip) values for the violin plot, which, for three groups, would be the means of the development rate for each group.

    df_E_old <- data.frame("Temp"=0:40, "dE_old"=sqrt(0:40)) |>
      mutate(LvlTemp=c(rep("low", 10), rep("medium", 11), rep("high", 20))) |>
      mutate(mean_dE=mean(dE_old), .by=LvlTemp)
    
    ggplot(df_E_old, aes(y = Temp)) +
      geom_path(aes(x = dE_old), color = "black", linewidth = 1) +
      geom_violin(aes(x = mean_dE, fill = LvlTemp, color = LvlTemp), 
                  alpha = 0.5, trim = TRUE) +
      coord_flip()
    

    enter image description here