Skip to content

Commit 6e8fcbb

Browse files
authored
Merge pull request matplotlib#27998 from saranti/orientation
Add a new `orientation` parameter to Violinplot and deprecate `vert`
2 parents 599a964 + bb34576 commit 6e8fcbb

File tree

7 files changed

+144
-36
lines changed

7 files changed

+144
-36
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
``violinplot`` and ``violin`` *vert* parameter
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
The parameter *vert: bool* has been deprecated on `~.Axes.violinplot` and
5+
`~.Axes.violin`.
6+
It will be replaced by *orientation: {"vertical", "horizontal"}* for API
7+
consistency.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
``violinplot`` and ``violin`` orientation parameter
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
Violinplots have a new parameter *orientation: {"vertical", "horizontal"}*
5+
to change the orientation of the plot. This will replace the deprecated
6+
*vert: bool* parameter.
7+
8+
9+
.. plot::
10+
:include-source: true
11+
:alt: Example of creating 4 horizontal violinplots.
12+
13+
import matplotlib.pyplot as plt
14+
import numpy as np
15+
16+
fig, ax = plt.subplots()
17+
np.random.seed(19680801)
18+
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
19+
20+
ax.violinplot(all_data, orientation='horizontal')
21+
plt.show()

galleries/examples/statistics/violinplot.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -62,37 +62,37 @@
6262
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
6363
axs[0, 5].set_title('Custom violin 6', fontsize=fs)
6464

65-
axs[1, 0].violinplot(data, pos, points=80, vert=False, widths=0.7,
65+
axs[1, 0].violinplot(data, pos, points=80, orientation='horizontal', widths=0.7,
6666
showmeans=True, showextrema=True, showmedians=True)
6767
axs[1, 0].set_title('Custom violin 7', fontsize=fs)
6868

69-
axs[1, 1].violinplot(data, pos, points=100, vert=False, widths=0.9,
69+
axs[1, 1].violinplot(data, pos, points=100, orientation='horizontal', widths=0.9,
7070
showmeans=True, showextrema=True, showmedians=True,
7171
bw_method='silverman')
7272
axs[1, 1].set_title('Custom violin 8', fontsize=fs)
7373

74-
axs[1, 2].violinplot(data, pos, points=200, vert=False, widths=1.1,
74+
axs[1, 2].violinplot(data, pos, points=200, orientation='horizontal', widths=1.1,
7575
showmeans=True, showextrema=True, showmedians=True,
7676
bw_method=0.5)
7777
axs[1, 2].set_title('Custom violin 9', fontsize=fs)
7878

79-
axs[1, 3].violinplot(data, pos, points=200, vert=False, widths=1.1,
79+
axs[1, 3].violinplot(data, pos, points=200, orientation='horizontal', widths=1.1,
8080
showmeans=True, showextrema=True, showmedians=True,
8181
quantiles=[[0.1], [], [], [0.175, 0.954], [0.75], [0.25]],
8282
bw_method=0.5)
8383
axs[1, 3].set_title('Custom violin 10', fontsize=fs)
8484

85-
axs[1, 4].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
86-
showmeans=True, showextrema=True, showmedians=True,
85+
axs[1, 4].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
86+
widths=1.1, showmeans=True, showextrema=True, showmedians=True,
8787
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5)
8888
axs[1, 4].set_title('Custom violin 11', fontsize=fs)
8989

90-
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
91-
showmeans=True, showextrema=True, showmedians=True,
90+
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
91+
widths=1.1, showmeans=True, showextrema=True, showmedians=True,
9292
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='low')
9393

94-
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, vert=False, widths=1.1,
95-
showmeans=True, showextrema=True, showmedians=True,
94+
axs[1, 5].violinplot(data[-1:], pos[-1:], points=200, orientation='horizontal',
95+
widths=1.1, showmeans=True, showextrema=True, showmedians=True,
9696
quantiles=[0.05, 0.1, 0.8, 0.9], bw_method=0.5, side='high')
9797
axs[1, 5].set_title('Custom violin 12', fontsize=fs)
9898

lib/matplotlib/axes/_axes.py

+53-14
Original file line numberDiff line numberDiff line change
@@ -8346,9 +8346,10 @@ def matshow(self, Z, **kwargs):
83468346

83478347
@_api.make_keyword_only("3.9", "vert")
83488348
@_preprocess_data(replace_names=["dataset"])
8349-
def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
8350-
showmeans=False, showextrema=True, showmedians=False,
8351-
quantiles=None, points=100, bw_method=None, side='both'):
8349+
def violinplot(self, dataset, positions=None, vert=None,
8350+
orientation='vertical', widths=0.5, showmeans=False,
8351+
showextrema=True, showmedians=False, quantiles=None,
8352+
points=100, bw_method=None, side='both',):
83528353
"""
83538354
Make a violin plot.
83548355
@@ -8366,9 +8367,21 @@ def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
83668367
The positions of the violins; i.e. coordinates on the x-axis for
83678368
vertical violins (or y-axis for horizontal violins).
83688369
8369-
vert : bool, default: True.
8370-
If true, creates a vertical violin plot.
8371-
Otherwise, creates a horizontal violin plot.
8370+
vert : bool, optional
8371+
.. deprecated:: 3.10
8372+
Use *orientation* instead.
8373+
8374+
If this is given during the deprecation period, it overrides
8375+
the *orientation* parameter.
8376+
8377+
If True, plots the violins vertically.
8378+
If False, plots the violins horizontally.
8379+
8380+
orientation : {'vertical', 'horizontal'}, default: 'vertical'
8381+
If 'horizontal', plots the violins horizontally.
8382+
Otherwise, plots the violins vertically.
8383+
8384+
.. versionadded:: 3.10
83728385
83738386
widths : float or array-like, default: 0.5
83748387
The maximum width of each violin in units of the *positions* axis.
@@ -8453,12 +8466,14 @@ def _kde_method(X, coords):
84538466
vpstats = cbook.violin_stats(dataset, _kde_method, points=points,
84548467
quantiles=quantiles)
84558468
return self.violin(vpstats, positions=positions, vert=vert,
8456-
widths=widths, showmeans=showmeans,
8457-
showextrema=showextrema, showmedians=showmedians, side=side)
8469+
orientation=orientation, widths=widths,
8470+
showmeans=showmeans, showextrema=showextrema,
8471+
showmedians=showmedians, side=side)
84588472

84598473
@_api.make_keyword_only("3.9", "vert")
8460-
def violin(self, vpstats, positions=None, vert=True, widths=0.5,
8461-
showmeans=False, showextrema=True, showmedians=False, side='both'):
8474+
def violin(self, vpstats, positions=None, vert=None,
8475+
orientation='vertical', widths=0.5, showmeans=False,
8476+
showextrema=True, showmedians=False, side='both'):
84628477
"""
84638478
Draw a violin plot from pre-computed statistics.
84648479
@@ -8496,9 +8511,21 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
84968511
The positions of the violins; i.e. coordinates on the x-axis for
84978512
vertical violins (or y-axis for horizontal violins).
84988513
8499-
vert : bool, default: True.
8500-
If true, plots the violins vertically.
8501-
Otherwise, plots the violins horizontally.
8514+
vert : bool, optional
8515+
.. deprecated:: 3.10
8516+
Use *orientation* instead.
8517+
8518+
If this is given during the deprecation period, it overrides
8519+
the *orientation* parameter.
8520+
8521+
If True, plots the violins vertically.
8522+
If False, plots the violins horizontally.
8523+
8524+
orientation : {'vertical', 'horizontal'}, default: 'vertical'
8525+
If 'horizontal', plots the violins horizontally.
8526+
Otherwise, plots the violins vertically.
8527+
8528+
.. versionadded:: 3.10
85028529
85038530
widths : float or array-like, default: 0.5
85048531
The maximum width of each violin in units of the *positions* axis.
@@ -8568,6 +8595,18 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
85688595
datashape_message = ("List of violinplot statistics and `{0}` "
85698596
"values must have the same length")
85708597

8598+
# vert and orientation parameters are linked until vert's
8599+
# deprecation period expires. If both are selected,
8600+
# vert takes precedence.
8601+
if vert is not None:
8602+
_api.warn_deprecated(
8603+
"3.10",
8604+
name="vert: bool",
8605+
alternative="orientation: {'vertical', 'horizontal'}"
8606+
)
8607+
orientation = 'vertical' if vert else 'horizontal'
8608+
_api.check_in_list(['horizontal', 'vertical'], orientation=orientation)
8609+
85718610
# Validate positions
85728611
if positions is None:
85738612
positions = range(1, N + 1)
@@ -8596,7 +8635,7 @@ def violin(self, vpstats, positions=None, vert=True, widths=0.5,
85968635
fillcolor = linecolor = self._get_lines.get_next_color()
85978636

85988637
# Check whether we are rendering vertically or horizontally
8599-
if vert:
8638+
if orientation == 'vertical':
86008639
fill = self.fill_betweenx
86018640
if side in ['low', 'high']:
86028641
perp_lines = functools.partial(self.hlines, colors=linecolor,

lib/matplotlib/axes/_axes.pyi

+4-2
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,8 @@ class Axes(_AxesBase):
739739
dataset: ArrayLike | Sequence[ArrayLike],
740740
positions: ArrayLike | None = ...,
741741
*,
742-
vert: bool = ...,
742+
vert: bool | None = ...,
743+
orientation: Literal["vertical", "horizontal"] = ...,
743744
widths: float | ArrayLike = ...,
744745
showmeans: bool = ...,
745746
showextrema: bool = ...,
@@ -758,7 +759,8 @@ class Axes(_AxesBase):
758759
vpstats: Sequence[dict[str, Any]],
759760
positions: ArrayLike | None = ...,
760761
*,
761-
vert: bool = ...,
762+
vert: bool | None = ...,
763+
orientation: Literal["vertical", "horizontal"] = ...,
762764
widths: float | ArrayLike = ...,
763765
showmeans: bool = ...,
764766
showextrema: bool = ...,

lib/matplotlib/pyplot.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -4159,7 +4159,8 @@ def triplot(*args, **kwargs):
41594159
def violinplot(
41604160
dataset: ArrayLike | Sequence[ArrayLike],
41614161
positions: ArrayLike | None = None,
4162-
vert: bool = True,
4162+
vert: bool | None = None,
4163+
orientation: Literal["vertical", "horizontal"] = "vertical",
41634164
widths: float | ArrayLike = 0.5,
41644165
showmeans: bool = False,
41654166
showextrema: bool = True,
@@ -4178,6 +4179,7 @@ def violinplot(
41784179
dataset,
41794180
positions=positions,
41804181
vert=vert,
4182+
orientation=orientation,
41814183
widths=widths,
41824184
showmeans=showmeans,
41834185
showextrema=showextrema,

lib/matplotlib/tests/test_axes.py

+46-9
Original file line numberDiff line numberDiff line change
@@ -3778,7 +3778,7 @@ def test_horiz_violinplot_baseline():
37783778
# First 9 digits of frac(sqrt(19))
37793779
np.random.seed(358898943)
37803780
data = [np.random.normal(size=100) for _ in range(4)]
3781-
ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
3781+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
37823782
showextrema=False, showmedians=False)
37833783

37843784

@@ -3788,7 +3788,7 @@ def test_horiz_violinplot_showmedians():
37883788
# First 9 digits of frac(sqrt(23))
37893789
np.random.seed(795831523)
37903790
data = [np.random.normal(size=100) for _ in range(4)]
3791-
ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
3791+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
37923792
showextrema=False, showmedians=True)
37933793

37943794

@@ -3798,7 +3798,7 @@ def test_horiz_violinplot_showmeans():
37983798
# First 9 digits of frac(sqrt(29))
37993799
np.random.seed(385164807)
38003800
data = [np.random.normal(size=100) for _ in range(4)]
3801-
ax.violinplot(data, positions=range(4), vert=False, showmeans=True,
3801+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=True,
38023802
showextrema=False, showmedians=False)
38033803

38043804

@@ -3808,7 +3808,7 @@ def test_horiz_violinplot_showextrema():
38083808
# First 9 digits of frac(sqrt(31))
38093809
np.random.seed(567764362)
38103810
data = [np.random.normal(size=100) for _ in range(4)]
3811-
ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
3811+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
38123812
showextrema=True, showmedians=False)
38133813

38143814

@@ -3818,7 +3818,7 @@ def test_horiz_violinplot_showall():
38183818
# First 9 digits of frac(sqrt(37))
38193819
np.random.seed(82762530)
38203820
data = [np.random.normal(size=100) for _ in range(4)]
3821-
ax.violinplot(data, positions=range(4), vert=False, showmeans=True,
3821+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=True,
38223822
showextrema=True, showmedians=True,
38233823
quantiles=[[0.1, 0.9], [0.2, 0.8], [0.3, 0.7], [0.4, 0.6]])
38243824

@@ -3829,7 +3829,7 @@ def test_horiz_violinplot_custompoints_10():
38293829
# First 9 digits of frac(sqrt(41))
38303830
np.random.seed(403124237)
38313831
data = [np.random.normal(size=100) for _ in range(4)]
3832-
ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
3832+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
38333833
showextrema=False, showmedians=False, points=10)
38343834

38353835

@@ -3839,7 +3839,7 @@ def test_horiz_violinplot_custompoints_200():
38393839
# First 9 digits of frac(sqrt(43))
38403840
np.random.seed(557438524)
38413841
data = [np.random.normal(size=100) for _ in range(4)]
3842-
ax.violinplot(data, positions=range(4), vert=False, showmeans=False,
3842+
ax.violinplot(data, positions=range(4), orientation='horizontal', showmeans=False,
38433843
showextrema=False, showmedians=False, points=200)
38443844

38453845

@@ -3850,11 +3850,11 @@ def test_violinplot_sides():
38503850
data = [np.random.normal(size=100)]
38513851
# Check horizontal violinplot
38523852
for pos, side in zip([0, -0.5, 0.5], ['both', 'low', 'high']):
3853-
ax.violinplot(data, positions=[pos], vert=False, showmeans=False,
3853+
ax.violinplot(data, positions=[pos], orientation='horizontal', showmeans=False,
38543854
showextrema=True, showmedians=True, side=side)
38553855
# Check vertical violinplot
38563856
for pos, side in zip([4, 3.5, 4.5], ['both', 'low', 'high']):
3857-
ax.violinplot(data, positions=[pos], vert=True, showmeans=False,
3857+
ax.violinplot(data, positions=[pos], orientation='vertical', showmeans=False,
38583858
showextrema=True, showmedians=True, side=side)
38593859

38603860

@@ -9065,3 +9065,40 @@ def test_latex_pie_percent(fig_test, fig_ref):
90659065

90669066
ax1 = fig_ref.subplots()
90679067
ax1.pie(data, autopct=r"%1.0f\%%", textprops={'usetex': True})
9068+
9069+
9070+
@check_figures_equal(extensions=['png'])
9071+
def test_violinplot_orientation(fig_test, fig_ref):
9072+
# Test the `orientation : {'vertical', 'horizontal'}`
9073+
# parameter and deprecation of `vert: bool`.
9074+
fig, axs = plt.subplots(nrows=1, ncols=3)
9075+
np.random.seed(19680801)
9076+
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
9077+
9078+
axs[0].violinplot(all_data) # Default vertical plot.
9079+
# xticks and yticks should be at their default position.
9080+
assert all(axs[0].get_xticks() == np.array(
9081+
[0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5]))
9082+
assert all(axs[0].get_yticks() == np.array(
9083+
[-30., -20., -10., 0., 10., 20., 30.]))
9084+
9085+
# Horizontal plot using new `orientation` keyword.
9086+
axs[1].violinplot(all_data, orientation='horizontal')
9087+
# xticks and yticks should be swapped.
9088+
assert all(axs[1].get_xticks() == np.array(
9089+
[-30., -20., -10., 0., 10., 20., 30.]))
9090+
assert all(axs[1].get_yticks() == np.array(
9091+
[0.5, 1., 1.5, 2., 2.5, 3., 3.5, 4., 4.5]))
9092+
9093+
plt.close()
9094+
9095+
# Deprecation of `vert: bool` keyword
9096+
with pytest.warns(mpl.MatplotlibDeprecationWarning,
9097+
match='vert: bool was deprecated in Matplotlib 3.10'):
9098+
# Compare images between a figure that
9099+
# uses vert and one that uses orientation.
9100+
ax_ref = fig_ref.subplots()
9101+
ax_ref.violinplot(all_data, vert=False)
9102+
9103+
ax_test = fig_test.subplots()
9104+
ax_test.violinplot(all_data, orientation='horizontal')

0 commit comments

Comments
 (0)