Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a60e49c

Browse filesBrowse files
committed
resolve merge conflicts
2 parents 68edfcb + d57fa97 commit a60e49c
Copy full SHA for a60e49c

File tree

Expand file treeCollapse file tree

7 files changed

+92
-23
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+92
-23
lines changed
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Add option to plot only one half of violin plot
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Setting the parameter *side* to 'low' or 'high' allows to only plot one half of the violin plot.

‎galleries/examples/statistics/violinplot.py

Copy file name to clipboardExpand all lines: galleries/examples/statistics/violinplot.py
+29-11Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,55 +28,73 @@
2828
pos = [1, 2, 4, 5, 7, 8]
2929
data = [np.random.normal(0, std, size=100) for std in pos]
3030

31-
fig, axs = plt.subplots(nrows=2, ncols=5, figsize=(10, 6))
31+
fig, axs = plt.subplots(nrows=2, ncols=6, figsize=(10, 4))
3232

3333
axs[0, 0].violinplot(data, pos, points=20, widths=0.3,
3434
showmeans=True, showextrema=True, showmedians=True)
35-
axs[0, 0].set_title('Custom violinplot 1', fontsize=fs)
35+
axs[0, 0].set_title('Custom violin 1', fontsize=fs)
3636

3737
axs[0, 1].violinplot(data, pos, points=40, widths=0.5,
3838
showmeans=True, showextrema=True, showmedians=True,
3939
bw_method='silverman')
40-
axs[0, 1].set_title('Custom violinplot 2', fontsize=fs)
40+
axs[0, 1].set_title('Custom violin 2', fontsize=fs)
4141

4242
axs[0, 2].violinplot(data, pos, points=60, widths=0.7, showmeans=True,
4343
showextrema=True, showmedians=True, bw_method=0.5)
44-
axs[0, 2].set_title('Custom violinplot 3', fontsize=fs)
44+
axs[0, 2].set_title('Custom violin 3', fontsize=fs)
4545

4646
axs[0, 3].violinplot(data, pos, points=60, widths=0.7, showmeans=True,
4747
showextrema=True, showmedians=True, bw_method=0.5,
4848
quantiles=[[0.1], [], [], [0.175, 0.954], [0.75], [0.25]])
49-
axs[0, 3].set_title('Custom violinplot 4', fontsize=fs)
49+
axs[0, 3].set_title('Custom violin 4', fontsize=fs)
5050

5151
axs[0, 4].violinplot(data[-1:], pos[-1:], points=60, widths=0.7,
5252
showmeans=True, showextrema=True, showmedians=True,
5353
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5)
54-
axs[0, 4].set_title('Custom violinplot 5', fontsize=fs)
54+
axs[0, 4].set_title('Custom violin 5', fontsize=fs)
55+
56+
axs[0, 5].violinplot(data[-1:], pos[-1:], points=60, widths=0.7,
57+
showmeans=True, showextrema=True, showmedians=True,
58+
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='low')
59+
60+
axs[0, 5].violinplot(data[-1:], pos[-1:], points=60, widths=0.7,
61+
showmeans=True, showextrema=True, showmedians=True,
62+
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
63+
axs[0, 5].set_title('Custom violin 6', fontsize=fs)
5564

5665
axs[1, 0].violinplot(data, pos, points=80, vert=False, widths=0.7,
5766
showmeans=True, showextrema=True, showmedians=True)
58-
axs[1, 0].set_title('Custom violinplot 6', fontsize=fs)
67+
axs[1, 0].set_title('Custom violin 7', fontsize=fs)
5968

6069
axs[1, 1].violinplot(data, pos, points=100, vert=False, widths=0.9,
6170
showmeans=True, showextrema=True, showmedians=True,
6271
bw_method='silverman')
63-
axs[1, 1].set_title('Custom violinplot 7', fontsize=fs)
72+
axs[1, 1].set_title('Custom violin 8', fontsize=fs)
6473

6574
axs[1, 2].violinplot(data, pos, points=200, vert=False, widths=1.1,
6675
showmeans=True, showextrema=True, showmedians=True,
6776
bw_method=0.5)
68-
axs[1, 2].set_title('Custom violinplot 8', fontsize=fs)
77+
axs[1, 2].set_title('Custom violin 9', fontsize=fs)
6978

7079
axs[1, 3].violinplot(data, pos, points=200, vert=False, widths=1.1,
7180
showmeans=True, showextrema=True, showmedians=True,
7281
quantiles=[[0.1], [], [], [0.175, 0.954], [0.75], [0.25]],
7382
bw_method=0.5)
74-
axs[1, 3].set_title('Custom violinplot 9', fontsize=fs)
83+
axs[1, 3].set_title('Custom violin 10', fontsize=fs)
7584

7685
axs[1, 4].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
7786
showmeans=True, showextrema=True, showmedians=True,
7887
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5)
79-
axs[1, 4].set_title('Custom violinplot 10', fontsize=fs)
88+
axs[1, 4].set_title('Custom violin 11', fontsize=fs)
89+
90+
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
91+
showmeans=True, showextrema=True, showmedians=True,
92+
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='low')
93+
94+
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
95+
showmeans=True, showextrema=True, showmedians=True,
96+
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
97+
axs[1, 5].set_title('Custom violin 12', fontsize=fs)
8098

8199

82100
for ax in axs.flat:

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+36-9Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8231,7 +8231,7 @@ def matshow(self, Z, **kwargs):
82318231
@_preprocess_data(replace_names=["dataset"])
82328232
def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
82338233
showmeans=False, showextrema=True, showmedians=False,
8234-
quantiles=None, points=100, bw_method=None):
8234+
quantiles=None, points=100, bw_method=None, side='both'):
82358235
"""
82368236
Make a violin plot.
82378237
@@ -8282,6 +8282,10 @@ def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
82828282
callable, it should take a `matplotlib.mlab.GaussianKDE` instance as
82838283
its only parameter and return a float.
82848284
8285+
side : {'both', 'low', 'high'}, default: 'both'
8286+
'both' plots standard violins. 'low'/'high' only
8287+
plots the side below/above the positions value.
8288+
82858289
data : indexable object, optional
82868290
DATA_PARAMETER_PLACEHOLDER
82878291
@@ -8333,10 +8337,10 @@ def _kde_method(X, coords):
83338337
quantiles=quantiles)
83348338
return self.violin(vpstats, positions=positions, vert=vert,
83358339
widths=widths, showmeans=showmeans,
8336-
showextrema=showextrema, showmedians=showmedians)
8340+
showextrema=showextrema, showmedians=showmedians, side=side)
83378341

83388342
def violin(self, vpstats, positions=None, vert=True, widths=0.5,
8339-
showmeans=False, showextrema=True, showmedians=False):
8343+
showmeans=False, showextrema=True, showmedians=False, side='both'):
83408344
"""
83418345
Draw a violin plot from pre-computed statistics.
83428346
@@ -8392,6 +8396,10 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
83928396
showmedians : bool, default: False
83938397
Whether to show the median with a line.
83948398
8399+
side : {'both', 'low', 'high'}, default: 'both'
8400+
'both' plots standard violins. 'low'/'high' only
8401+
plots the side below/above the positions value.
8402+
83958403
Returns
83968404
-------
83978405
dict
@@ -8454,8 +8462,13 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84548462
elif len(widths) != N:
84558463
raise ValueError(datashape_message.format("widths"))
84568464

8465+
# Validate side
8466+
_api.check_in_list(["both", "low", "high"], side=side)
8467+
84578468
# Calculate ranges for statistics lines (shape (2, N)).
8458-
line_ends = [[-0.25], [0.25]] * np.array(widths) + positions
8469+
line_ends = [[-0.25 if side in ['both', 'low'] else 0],
8470+
[0.25 if side in ['both', 'high'] else 0]] \
8471+
* np.array(widths) + positions
84598472

84608473
# Colors.
84618474
if mpl.rcParams['_internal.classic_mode']:
@@ -8467,20 +8480,34 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84678480
# Check whether we are rendering vertically or horizontally
84688481
if vert:
84698482
fill = self.fill_betweenx
8470-
perp_lines = functools.partial(self.hlines, colors=linecolor)
8471-
par_lines = functools.partial(self.vlines, colors=linecolor)
8483+
if side in ['low', 'high']:
8484+
perp_lines = functools.partial(self.hlines, colors=linecolor,
8485+
capstyle='projecting')
8486+
par_lines = functools.partial(self.vlines, colors=linecolor,
8487+
capstyle='projecting')
8488+
else:
8489+
perp_lines = functools.partial(self.hlines, colors=linecolor)
8490+
par_lines = functools.partial(self.vlines, colors=linecolor)
84728491
else:
84738492
fill = self.fill_between
8474-
perp_lines = functools.partial(self.vlines, colors=linecolor)
8475-
par_lines = functools.partial(self.hlines, colors=linecolor)
8493+
if side in ['low', 'high']:
8494+
perp_lines = functools.partial(self.vlines, colors=linecolor,
8495+
capstyle='projecting')
8496+
par_lines = functools.partial(self.hlines, colors=linecolor,
8497+
capstyle='projecting')
8498+
else:
8499+
perp_lines = functools.partial(self.vlines, colors=linecolor)
8500+
par_lines = functools.partial(self.hlines, colors=linecolor)
84768501

84778502
# Render violins
84788503
bodies = []
84798504
for stats, pos, width in zip(vpstats, positions, widths):
84808505
# The 0.5 factor reflects the fact that we plot from v-p to v+p.
84818506
vals = np.array(stats['vals'])
84828507
vals = 0.5 * width * vals / vals.max()
8483-
bodies += [fill(stats['coords'], -vals + pos, vals + pos,
8508+
bodies += [fill(stats['coords'],
8509+
-vals + pos if side in ['both', 'low'] else pos,
8510+
vals + pos if side in ['both', 'high'] else pos,
84848511
facecolor=fillcolor, alpha=0.3)]
84858512
means.append(stats['mean'])
84868513
mins.append(stats['min'])

‎lib/matplotlib/axes/_axes.pyi

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.pyi
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,7 @@ class Axes(_AxesBase):
744744
| float
745745
| Callable[[GaussianKDE], float]
746746
| None = ...,
747+
side: Literal["both", "low", "high"] = ...,
747748
*,
748749
data=...,
749750
) -> dict[str, Collection]: ...
@@ -756,6 +757,7 @@ class Axes(_AxesBase):
756757
showmeans: bool = ...,
757758
showextrema: bool = ...,
758759
showmedians: bool = ...,
760+
side: Literal["both", "low", "high"] = ...,
759761
) -> dict[str, Collection]: ...
760762

761763
table = mtable.table

‎lib/matplotlib/pyplot.py

Copy file name to clipboardExpand all lines: lib/matplotlib/pyplot.py
+6-3Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4078,9 +4078,11 @@ def violinplot(
40784078
showmedians: bool = False,
40794079
quantiles: Sequence[float | Sequence[float]] | None = None,
40804080
points: int = 100,
4081-
bw_method: (
4082-
Literal["scott", "silverman"] | float | Callable[[GaussianKDE], float] | None
4083-
) = None,
4081+
bw_method: Literal["scott", "silverman"]
4082+
| float
4083+
| Callable[[GaussianKDE], float]
4084+
| None = None,
4085+
side: Literal["both", "low", "high"] = "both",
40844086
*,
40854087
data=None,
40864088
) -> dict[str, Collection]:
@@ -4095,6 +4097,7 @@ def violinplot(
40954097
quantiles=quantiles,
40964098
points=points,
40974099
bw_method=bw_method,
4100+
side=side,
40984101
**({"data": data} if data is not None else {}),
40994102
)
41004103

Loading

‎lib/matplotlib/tests/test_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_axes.py
+15Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3794,6 +3794,21 @@ def test_horiz_violinplot_custompoints_200():
37943794
showextrema=False, showmedians=False, points=200)
37953795

37963796

3797+
@image_comparison(['violinplot_sides.png'], remove_text=True, style='mpl20')
3798+
def test_violinplot_sides():
3799+
ax = plt.axes()
3800+
np.random.seed(19680801)
3801+
data = [np.random.normal(size=100)]
3802+
# Check horizontal violinplot
3803+
for pos, side in zip([0, -0.5, 0.5], ['both', 'low', 'high']):
3804+
ax.violinplot(data, positions=[pos], vert=False, showmeans=False,
3805+
showextrema=True, showmedians=True, side=side)
3806+
# Check vertical violinplot
3807+
for pos, side in zip([4, 3.5, 4.5], ['both', 'low', 'high']):
3808+
ax.violinplot(data, positions=[pos], vert=True, showmeans=False,
3809+
showextrema=True, showmedians=True, side=side)
3810+
3811+
37973812
def test_violinplot_bad_positions():
37983813
ax = plt.axes()
37993814
# First 9 digits of frac(sqrt(47))

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.