Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a60e49c

Browse files
committed
resolve merge conflicts
2 parents 68edfcb + d57fa97 commit a60e49c

File tree

7 files changed

+92
-23
lines changed

7 files changed

+92
-23
lines changed
Lines 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

Lines 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

Lines 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

Lines 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

Lines 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

lib/matplotlib/tests/test_axes.py

Lines 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)