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 013757e

Browse filesBrowse files
committed
resolve conflicts
2 parents 9c033d2 + a60e49c commit 013757e
Copy full SHA for 013757e

File tree

Expand file treeCollapse file tree

7 files changed

+93
-24
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+93
-24
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
@@ -8244,7 +8244,7 @@ def matshow(self, Z, **kwargs):
82448244
@_preprocess_data(replace_names=["dataset"])
82458245
def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
82468246
showmeans=False, showextrema=True, showmedians=False,
8247-
quantiles=None, points=100, bw_method=None):
8247+
quantiles=None, points=100, bw_method=None, side='both'):
82488248
"""
82498249
Make a violin plot.
82508250
@@ -8295,6 +8295,10 @@ def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
82958295
callable, it should take a `matplotlib.mlab.GaussianKDE` instance as
82968296
its only parameter and return a float.
82978297
8298+
side : {'both', 'low', 'high'}, default: 'both'
8299+
'both' plots standard violins. 'low'/'high' only
8300+
plots the side below/above the positions value.
8301+
82988302
data : indexable object, optional
82998303
DATA_PARAMETER_PLACEHOLDER
83008304
@@ -8346,10 +8350,10 @@ def _kde_method(X, coords):
83468350
quantiles=quantiles)
83478351
return self.violin(vpstats, positions=positions, vert=vert,
83488352
widths=widths, showmeans=showmeans,
8349-
showextrema=showextrema, showmedians=showmedians)
8353+
showextrema=showextrema, showmedians=showmedians, side=side)
83508354

83518355
def violin(self, vpstats, positions=None, vert=True, widths=0.5,
8352-
showmeans=False, showextrema=True, showmedians=False):
8356+
showmeans=False, showextrema=True, showmedians=False, side='both'):
83538357
"""
83548358
Draw a violin plot from pre-computed statistics.
83558359
@@ -8405,6 +8409,10 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84058409
showmedians : bool, default: False
84068410
Whether to show the median with a line.
84078411
8412+
side : {'both', 'low', 'high'}, default: 'both'
8413+
'both' plots standard violins. 'low'/'high' only
8414+
plots the side below/above the positions value.
8415+
84088416
Returns
84098417
-------
84108418
dict
@@ -8467,8 +8475,13 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84678475
elif len(widths) != N:
84688476
raise ValueError(datashape_message.format("widths"))
84698477

8478+
# Validate side
8479+
_api.check_in_list(["both", "low", "high"], side=side)
8480+
84708481
# Calculate ranges for statistics lines (shape (2, N)).
8471-
line_ends = [[-0.25], [0.25]] * np.array(widths) + positions
8482+
line_ends = [[-0.25 if side in ['both', 'low'] else 0],
8483+
[0.25 if side in ['both', 'high'] else 0]] \
8484+
* np.array(widths) + positions
84728485

84738486
# Colors.
84748487
if mpl.rcParams['_internal.classic_mode']:
@@ -8480,20 +8493,34 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84808493
# Check whether we are rendering vertically or horizontally
84818494
if vert:
84828495
fill = self.fill_betweenx
8483-
perp_lines = functools.partial(self.hlines, colors=linecolor)
8484-
par_lines = functools.partial(self.vlines, colors=linecolor)
8496+
if side in ['low', 'high']:
8497+
perp_lines = functools.partial(self.hlines, colors=linecolor,
8498+
capstyle='projecting')
8499+
par_lines = functools.partial(self.vlines, colors=linecolor,
8500+
capstyle='projecting')
8501+
else:
8502+
perp_lines = functools.partial(self.hlines, colors=linecolor)
8503+
par_lines = functools.partial(self.vlines, colors=linecolor)
84858504
else:
84868505
fill = self.fill_between
8487-
perp_lines = functools.partial(self.vlines, colors=linecolor)
8488-
par_lines = functools.partial(self.hlines, colors=linecolor)
8506+
if side in ['low', 'high']:
8507+
perp_lines = functools.partial(self.vlines, colors=linecolor,
8508+
capstyle='projecting')
8509+
par_lines = functools.partial(self.hlines, colors=linecolor,
8510+
capstyle='projecting')
8511+
else:
8512+
perp_lines = functools.partial(self.vlines, colors=linecolor)
8513+
par_lines = functools.partial(self.hlines, colors=linecolor)
84898514

84908515
# Render violins
84918516
bodies = []
84928517
for stats, pos, width in zip(vpstats, positions, widths):
84938518
# The 0.5 factor reflects the fact that we plot from v-p to v+p.
84948519
vals = np.array(stats['vals'])
84958520
vals = 0.5 * width * vals / vals.max()
8496-
bodies += [fill(stats['coords'], -vals + pos, vals + pos,
8521+
bodies += [fill(stats['coords'],
8522+
-vals + pos if side in ['both', 'low'] else pos,
8523+
vals + pos if side in ['both', 'high'] else pos,
84978524
facecolor=fillcolor, alpha=0.3)]
84988525
means.append(stats['mean'])
84998526
mins.append(stats['min'])

‎lib/matplotlib/axes/_axes.pyi

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.pyi
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ class Axes(_AxesBase):
370370
autorange: bool = ...,
371371
zorder: float | None = ...,
372372
capwidths: float | ArrayLike | None = ...,
373-
label: Sequence[str] | None = ...,
373+
label: Sequence[str] | None = ...,
374374
*,
375375
data=...,
376376
) -> dict[str, Any]: ...
@@ -745,6 +745,7 @@ class Axes(_AxesBase):
745745
| float
746746
| Callable[[GaussianKDE], float]
747747
| None = ...,
748+
side: Literal["both", "low", "high"] = ...,
748749
*,
749750
data=...,
750751
) -> dict[str, Collection]: ...
@@ -757,6 +758,7 @@ class Axes(_AxesBase):
757758
showmeans: bool = ...,
758759
showextrema: bool = ...,
759760
showmedians: bool = ...,
761+
side: Literal["both", "low", "high"] = ...,
760762
) -> dict[str, Collection]: ...
761763

762764
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.