Search code examples
rgraphggplot2density-plot

ggplot: Add a theoretical range on a geom_violin()


Let's say we observed two species of beetles. We want to compare their size using geom_violin() as done below:

df = data.frame(species=rep(c('species_a','species_b'),3), size=c(1,1.5,1.2,1.8,1.1,1.9))
ggplot(df, aes(x=species, y=size)) + geom_violin()

Knowing that the expected size range is [0.8,1.8] for species_a and [1.2, 1.8] for species_b...

ranges = list(species_a=c(0.8,1.8), species_b=c(1.2,1.8))

How can we easily add this range (with a grey shape for example) on the graph?


Solution

  • Put ranges in separate data frame with species names and minimal/maximal values

    ranges = data.frame(species=c('species_a','species_b'), 
                        rmin=c(0.8,1.2),rmax=c(1.2,1.8))
    ranges
    
        species rmin rmax
    1 species_a  0.8  1.8
    2 species_b  1.2  1.8
    

    Then use new data frame for geom_rect() to make area that is placed under the geom_violin(). The geom_blank() is used to make x axis according to original data frame.

    ggplot(df, aes(x=species, y=size))  + geom_blank() + 
      geom_rect(data=ranges,aes(xmin=as.numeric(species)-0.45,
                                xmax=as.numeric(species)+0.45,
                                ymin=rmin,ymax=rmax),inherit.aes=FALSE)+
      geom_violin()
    

    enter image description here