2
votes

I'm trying to plot one full violin plot next to multiple half-violin plots using ggplot. I'm plotting the full violin plot using geom_violin(), and plotting the half violin plots using geom_violinhalf from the "see" package, with scale = 'width'. However, this produced a figure with the full violin plot appearing significantly thinner than the half-violin plots, as seen in the code below. I've tried the three built-in "scale" options in ggplot.

Is there a way to plot one full violin plot and several half-violin plots using one function? Or is there a different way I can manually set the width of the full violin plot?

Thanks!

#install.packages("vioplot")
#install.packages('ggplot2')
#install.packages('scales')
library(ggplot2)
library(vioplot)
library(scales)

df1 = as.data.frame(matrix(NA, nrow = 1000, ncol = 2))
colnames(df1) = c('x','y')
df1[,2] = rnorm(1000,10,5)
df1[,1] = rep(-5, 1000)
df2 = as.data.frame(matrix(NA, nrow = 10000, ncol = 2))
colnames(df2) = c('x','y')
df2[,1] = sample(seq(0,70,5),10000,replace=TRUE)
df2[,2] = rnorm(10000,10,5)
df = rbind(df1, df2)

ggplot(df, aes(x=x,y=y))+
  geom_violinhalf(data=subset(df,df$x != -5), aes(x=x, group = x), scale = 'width', fill = alpha('red', 0.2), color = alpha('red',0.2))+
  geom_violin(data = subset(df, df$x== -5), color = alpha('red', 0.2), fill = alpha('red', 0.2))+
  geom_point(size = 1.2, col = alpha('grey', 0.2))+
  theme_classic()

EDIT

The previous code was incorrect, apologies. How could the first violin be expanded if the dataframe was instead as follows, with each of the violin plots grouped by 'd' instead of by 'x':

df1 = as.data.frame(matrix(NA, nrow = 10000, ncol = 3))
colnames(df1) = c('d','y','x')
df1[,2] = rnorm(10000,10,5)
df1[,1] = sample(seq(-5,70,.1),10000, replace=TRUE)
for(i in 1:nrow(df1)){
  if(df1[i,'d'] < 0){df1[i,"x"] <- -5}else
    if(df1[i,"d"] >= 0 & df1[i,"d"] < 5){df1[i,"x"] <- 0}else
      if(df1[i,"d"] >= 5 & df1[i,"d"] < 10){df1[i,"x"] <- 5}else
        if(df1[i,"d"] >= 10 & df1[i,"d"] < 15){df1[i,"x"] <- 10}else
          if(df1[i,"d"] >=15 & df1[i,"d"] < 20){df1[i,"x"] <- 15}else
            if(df1[i,"d"] >= 20 & df1[i,"d"] < 25){df1[i,"x"] <- 20}else
              if(df1[i,"d"] >= 25 & df1[i,"d"] < 30){df1[i,"x"] <- 25}else
                if(df1[i,"d"] >= 30 & df1[i,"d"] < 35){df1[i,"x"] <- 30}else
                  if(df1[i,"d"] >= 35 & df1[i,"d"] < 40){df1[i,"x"] <- 35}else
                    if(df1[i,"d"] >= 40 & df1[i,"d"] < 45){df1[i,"x"] <- 40}else
                      if(df1[i,"d"] >= 45 & df1[i,"d"] < 50){df1[i,"x"] <- 45}else
                        if(df1[i,"d"] >= 50 & df1[i,"d"] < 55){df1[i,"x"] <- 50}else
                          if(df1[i,"d"] >= 55 & df1[i,"d"] < 60){df1[i,"x"] <- 55}else
                            if(df1[i,"d"] >= 60 & df1[i,"d"] < 65){df1[i,"x"] <- 60}else
                              if(df1[i,"d"] >= 65 & df1[i,"d"] < 70){df1[i,"x"] <- 65}else
                                if(df1[i,"d"] >= 70 & df1[i,"d"] < 75){df1[i,"x"] <- 70}else
                                  if(df1[i,"d"] >= 75 & df1[i,"d"] < 80){df1[i,"x"] <- 75}}
1
You might be interested in this github.com/RainCloudPlots/RainCloudPlotsTung

1 Answers

3
votes

The widths will equalize by default if you convert x to a factor:

ggplot(df, aes(x=factor(x),y=y)) +
  geom_violinhalf(data=subset(df,df$x != -5), aes(group = x), 
                  scale = 'width', fill = alpha('red', 0.2), 
                  color = alpha('red',0.2)) +
  geom_violin(data = subset(df, df$x== -5), 
              color = alpha('red', 0.2), fill = alpha('red', 0.2)) +
  geom_point(size = 1.2, col = alpha('grey', 0.2)) +
  theme_classic()

enter image description here

Alternatively, you can keep x numeric and use the width parsmeter of geom_violin. Here I'll set it a bit too wide at width = 8 for demonstration purposes, but the ideal seems to be about width = 5:

ggplot(df, aes(x = x, y = y)) +
  geom_violinhalf(data = subset(df,df$x != -5), aes(group = x), 
                  scale = 'width', fill = alpha('red', 0.2), 
                  color = alpha('red',0.2)) +
  geom_violin(data = subset(df, df$x == -5), width = 8,
              color = alpha('red', 0.2), fill = alpha('red', 0.2)) +
  geom_point(size = 1.2, col = alpha('grey', 0.2)) +
  theme_classic()

enter image description here


EDIT

To add the points from column d, we can do:

ggplot(df1, aes(x=x,y=y)) +
  geom_violinhalf(data=subset(df1,df1$x != -5), aes(group = x), 
                  scale = 'width', fill = alpha('red', 0.2), 
                  color = alpha('red',0.2)) +
  geom_violin(data = subset(df1, df1$x== -5), width = 5, 
              color = alpha('red', 0.2), fill = alpha('red', 0.2)) +
  geom_point(aes(x = d), size = 1.2, col = alpha('grey', 0.2)) +
  theme_classic()

enter image description here