Violin Plots with violinplot(D)ΒΆ

A violin plot combines a box plot with a kernel density estimate (KDE), showing the full distribution shape as a mirrored density curve on each side. The Axes.violinplot() method takes a 2D array of data and renders one violin for each column, with the width of the violin at any point proportional to the local density of observations.

Why this matters for data science: Violin plots reveal distribution features that box plots hide – bimodality, skewness, and the detailed shape of the probability density. Two distributions can have identical medians and IQRs (making their box plots look the same) while having completely different shapes that violin plots clearly distinguish. They are especially valuable when comparing distributions across groups in EDA, evaluating model predictions across categories, and anywhere that the full distribution shape matters more than just summary statistics. The example generates three distributions with different means (3, 5, 4) and standard deviations (0.75, 1.00, 0.75) using np.random.normal(). The showmeans=False, showmedians=False, showextrema=False settings remove the default internal markers for a cleaner look, and body.set_alpha(0.9) makes the violins nearly opaque. You can re-enable these markers or add a box plot overlay for a combined visualization.

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('_mpl-gallery')

# make data:
np.random.seed(10)
D = np.random.normal((3, 5, 4), (0.75, 1.00, 0.75), (200, 3))

# plot:
fig, ax = plt.subplots()

vp = ax.violinplot(D, [2, 4, 6], widths=2,
                   showmeans=False, showmedians=False, showextrema=False)
# styling:
for body in vp['bodies']:
    body.set_alpha(0.9)
ax.set(xlim=(0, 8), xticks=np.arange(1, 8),
       ylim=(0, 8), yticks=np.arange(1, 8))

plt.show()