Recently matplotlib has added a native support for violin plot. What I want to do is half-violin plot. I guess that it can be done changing the body
the function is returning. Do you know how to plot half violin plot as in the example but using the new function from matplotlib?
Half violin plot in matplotlib
Asked Answered
seaborn does paired half violins, might be easier to start there: stanford.edu/~mwaskom/software/seaborn-dev/generated/… –
Primm
The Stanford link in the comments appears to be dead. –
Newsmonger
@PhilB Seaborn now has its doc pages at pydata: seaborn.pydata.org/generated/seaborn.violinplot.html –
Usquebaugh
Here simplify modifying the patches, clipping the values on the right or left
data1 = (np.random.normal(0, 1, size=10000), np.random.normal(0, 2, size=10000))
data2 = (np.random.normal(1, 1, size=10000), np.random.normal(1, 2, size=10000))
fig, ax = plt.subplots(figsize=(18, 7))
v1 = ax.violinplot(data1, points=100, positions=np.arange(0, len(data1)),
showmeans=False, showextrema=False, showmedians=False)
for b in v1['bodies']:
# get the center
m = np.mean(b.get_paths()[0].vertices[:, 0])
# modify the paths to not go further right than the center
b.get_paths()[0].vertices[:, 0] = np.clip(b.get_paths()[0].vertices[:, 0], -np.inf, m)
b.set_color('r')
v2 = ax.violinplot(data2, points=100, positions=np.arange(0, len(data2)),
showmeans=False, showextrema=False, showmedians=False)
for b in v2['bodies']:
# get the center
m = np.mean(b.get_paths()[0].vertices[:, 0])
# modify the paths to not go further left than the center
b.get_paths()[0].vertices[:, 0] = np.clip(b.get_paths()[0].vertices[:, 0], m, np.inf)
b.set_color('b')
ax.legend([v1['bodies'][0],v2['bodies'][0]],['data1', 'data2'])
with some comments, it may help... TY –
Terra
For those using horizontal violin plots
vert=False
, to make this work, just swap out .vertices[:, 0]
with .vertices[:, 1]
. –
Flogging New in matplotlib 3.9
ax.violinplot
now includes a side
param to automatically plot only one half.
Now it's as simple as setting side="low"
and side="high"
respectively:
v1 = ax.violinplot(data1, showmeans=False, showextrema=False, showmedians=False,
side="low") # `side` param requires matplotlib 3.9+
v2 = ax.violinplot(data2, showmeans=False, showextrema=False, showmedians=False,
side="high") # `side` param requires matplotlib 3.9+
As of 3.9 you can now use the side
parameter to set this:
# Fake data with reproducible random state. np.random.seed(19680801) data = np.random.normal(0, 8, size=100) fig, ax = plt.subplots() ax.violinplot(data, [0], showmeans=True, showextrema=True) ax.violinplot(data, [1], showmeans=True, showextrema=True, side='low') ax.violinplot(data, [2], showmeans=True, showextrema=True, side='high') ax.set_title('Violin Sides Example') ax.set_xticks([0, 1, 2], ['Default', 'side="low"', 'side="high"']) ax.set_yticklabels([])
© 2022 - 2025 — McMap. All rights reserved.