Search code examples
rggplot2layerviolin-plotjitter

Add new geom as new row in ggplot2, preventing layering of plots


I am pretty sure that this is easy to do but I can't seem to find a proper way to query this question into google or stack, so here we are:

I have a plot made in ggplot2 which makes use of geom_jitter(), efficiently creating one row for each element in a factor and plotting its values. I would like to add a complementary geom_violin() to the plot, but just adding the extra geom_ function to the plot code returns two layers: the jitter and the violin, one on top of the other (as usually expected).

EDIT:

This is how the plot looks like: enter image description here How can I have the violin as a separate row, without generating a second plot? Side quest: how I can I have the jitter and the violin geoms interleaved? (i.e. element A jitter row followed by element A violin row, and then element B jitter row followed by element B violin row)

This is the minimum required code to make it (without all the theme() embellishments):

P1 <- ggplot(data=TEST_STACK_SUB, aes(x=E, y=C, col=A)) + 
theme(... , aspect.ratio=0.3) + 
geom_point(position = position_jitter(w = 0.30, h = 0), alpha=0.2, size=0.5) +
geom_violin(data=TEST_STACK_SUB, mapping=aes(x=E, y=C), position="dodge") +
scale_x_discrete() +
scale_y_continuous(limits=c(0,1), breaks=seq(0,1,0.1), 
                  labels=c(seq(0,1,0.1))) + 
scale_color_gradient2(breaks=seq(0,100,20), 
                      limits=c(0,100), 
                      low="green3",
                      high="darkorchid4",
                      midpoint=50,
                      name="") +
coord_flip()

options(repr.plot.width=8, repr.plot.height=2)
plot(P1)

Here is a subset of the data to generate it (for you to try): data


Solution

  • How about manipulating your factor as a continuous variable and nudging the entries across the aes() calls like so:

    library(dplyr)
    library(ggplot2)
    
    set.seed(42)
    
    tibble(x = rep(c(1, 3), each = 10), 
           y = c(rnorm(10, 2), rnorm(10))) -> plot_data
    
    ggplot(plot_data) + 
      geom_jitter(aes(x = x - 0.5, y = y), width = 0.25) + 
      geom_violin(aes(x = x + 0.5, y = y, group = x), width = 0.5) + 
      coord_flip() + 
      labs(x = "x") + 
      scale_x_continuous(breaks = c(1, 3), 
                         labels = paste("Level", 1:2), 
                         trans = scales::reverse_trans())
    

    plot output