Half violin plot in matplotlib
Asked Answered
B

3

16

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?

Bedmate answered 21/4, 2015 at 15:6 Comment(3)
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.htmlUsquebaugh
B
31

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'])

enter image description here

Bedmate answered 21/4, 2015 at 20:0 Comment(2)
with some comments, it may help... TYTerra
For those using horizontal violin plots vert=False, to make this work, just swap out .vertices[:, 0] with .vertices[:, 1].Flogging
R
1

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+

violinplots using new side param

Richardricharda answered 16/5, 2024 at 15:26 Comment(0)
L
1

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([])

enter image description here

Lubricious answered 19/5, 2024 at 4:39 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.