R Graphics · Violin Plot

Comparing Distribution Shapes with Violin Plots in R

Build single, grouped, split-style, box-overlay, point-overlay, and ggplot2 violins.

6 examplesReproducible R code
Before you begin

Choose the variation that serves the analysis

Violin plots mirror a density estimate around a central axis. They reveal distributional shape while retaining the compact group-comparison role of a boxplot.

Examples
06
Levels
Beginner + Intermediate
01
Example 01Base RBeginner

Draw a Basic Violin Plot

A violin plot mirrors a density curve to show the full distribution shape.

Draw a Basic Violin Plot example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
x<-iris$Sepal.Length;d<-density(x);w<-d$y/max(d$y)*.4
plot(1,type="n",xlim=c(.4,1.6),ylim=range(d$x),xaxt="n",xlab="",ylab="Sepal length")
polygon(c(1-w,rev(1+w)),c(d$x,rev(d$x)),col="#93c5fd",border="#2563eb")
02
Example 02Base RBeginner

Compare Several Violins

Grouped violins expose differences in modality, spread, and center across categories.

Compare Several Violins example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
groups<-split(iris$Sepal.Length,iris$Species);plot(1,type="n",xlim=c(.5,3.5),ylim=range(iris$Sepal.Length),xaxt="n")
for(i in 1:3){d<-density(groups[[i]]);w<-d$y/max(d$y)*.35;polygon(c(i-w,rev(i+w)),c(d$x,rev(d$x)),col=adjustcolor(c("#2563eb","#0891b2","#f59e0b")[i],.45))};axis(1,1:3,names(groups))
03
Example 03Base RBeginner

Overlay a Boxplot

A narrow boxplot adds the median and quartiles to the density shape.

Overlay a Boxplot example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
library(ggplot2)
ggplot(iris,aes(Species,Sepal.Length,fill=Species))+geom_violin(show.legend=FALSE)+geom_boxplot(width=.12,fill="white",show.legend=FALSE)+theme_minimal()
04
Example 04Base RIntermediate

Overlay Individual Observations

Jittered points reconnect the smoothed violin to the underlying sample.

Overlay Individual Observations example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
library(ggplot2)
ggplot(iris,aes(Species,Sepal.Length,fill=Species))+geom_violin(alpha=.5)+geom_jitter(width=.08,size=1,alpha=.5)+theme_minimal()
05
Example 05Base RIntermediate

Control the Density Tails

Trimmed and untrimmed violins differ in whether the shape extends beyond observed extremes.

Control the Density Tails example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
library(ggplot2)
ggplot(iris,aes(Species,Sepal.Length,fill=Species))+geom_violin(trim=FALSE,show.legend=FALSE)+theme_minimal()
06
Example 06Base RIntermediate

Turn Violins Horizontally

Horizontal violins accommodate long category labels and emphasize the value scale.

Turn Violins Horizontally example generated in R
R-generated example output.

Run the code, inspect how the visual encoding changes, and adapt the labels, scales, and styling to the analytical question rather than treating the defaults as fixed.

RRun this code
library(ggplot2)
ggplot(iris,aes(Species,Sepal.Length,fill=Species))+geom_violin(show.legend=FALSE)+coord_flip()+theme_minimal()