Skip to content

Commit ff7591f

Browse files
committed
Deprecate boxplot(..., whis="range").
It's a special-case that needs its own testing and documentation, when it can be perfectly well folded into `whis=(percentile, percentile)` (specifically, `whis=(0, 100)`).
1 parent 6ce2638 commit ff7591f

File tree

7 files changed

+59
-38
lines changed

7 files changed

+59
-38
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Deprecations
2+
````````````
3+
4+
Setting the ``whis`` parameter of `.Axes.boxplot` and `.cbook.boxplot_stats` to
5+
"range" to mean "the whole data range" is deprecated; set it to (0, 100) (which
6+
gets interpreted as percentiles) to achieve the same effect.

examples/statistics/boxplot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@
7474
axs[0, 1].boxplot(data, flierprops=flierprops, medianprops=medianprops)
7575
axs[0, 1].set_title('Custom medianprops\nand flierprops', fontsize=fs)
7676

77-
axs[0, 2].boxplot(data, whis='range')
78-
axs[0, 2].set_title('whis="range"', fontsize=fs)
77+
axs[0, 2].boxplot(data, whis=(0, 100))
78+
axs[0, 2].set_title('whis=(0, 100)', fontsize=fs)
7979

8080
axs[1, 0].boxplot(data, meanprops=meanpointprops, meanline=False,
8181
showmeans=True)

lib/matplotlib/axes/_axes.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3503,18 +3503,23 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
35033503
everything is drawn horizontally.
35043504
35053505
whis : float, sequence, or string (default = 1.5)
3506-
As a float, determines the reach of the whiskers beyond the
3507-
first and third quartiles. In other words, where IQR is the
3508-
interquartile range (`Q3-Q1`), the upper whisker will extend to
3509-
last datum less than `Q3 + whis*IQR`). Similarly, the lower whisker
3510-
will extend to the first datum greater than `Q1 - whis*IQR`.
3511-
Beyond the whiskers, data
3512-
are considered outliers and are plotted as individual
3513-
points. Alternatively, set
3514-
this to an ascending sequence of percentile (e.g., [5, 95])
3515-
to set the whiskers at specific percentiles of the data.
3516-
Finally, ``whis`` can be the string ``'range'`` to force the
3517-
whiskers to the min and max of the data.
3506+
The position of the whiskers.
3507+
3508+
If a float, the lower whisker is at position ``Q1 - whis*(Q3-Q1)``,
3509+
and the upper whisker at position ``Q3 + whis*(Q3-Q1)``, where Q1
3510+
and Q3 are the first and third quartiles.
3511+
3512+
If a pair of floats, they indicate the percentiles at which to
3513+
draw the whiskers (e.g., (5, 95)). In particular, setting this to
3514+
[0, 100] results in whiskers covering the whole range of the data.
3515+
"range" is a deprecated synonym for (0, 100).
3516+
3517+
In the edge case where ``Q1 == Q3``, *whis* is automatically set
3518+
to [0, 100] (cover the whole range of the data) if *autorange* is
3519+
True.
3520+
3521+
Beyond the whiskers, data are considered outliers and are plotted
3522+
as individual points.
35183523
35193524
bootstrap : int, optional
35203525
Specifies whether to bootstrap the confidence intervals
@@ -3567,7 +3572,7 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
35673572
35683573
autorange : bool, optional (False)
35693574
When `True` and the data are distributed such that the 25th and
3570-
75th percentiles are equal, ``whis`` is set to ``'range'`` such
3575+
75th percentiles are equal, ``whis`` is set to (0, 100) such
35713576
that the whisker ends are at the minimum and maximum of the data.
35723577
35733578
meanline : bool, optional (False)

lib/matplotlib/cbook/__init__.py

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1039,20 +1039,23 @@ def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None,
10391039
Data that will be represented in the boxplots. Should have 2 or
10401040
fewer dimensions.
10411041
1042-
whis : float, string, or sequence (default = 1.5)
1043-
As a float, determines the reach of the whiskers beyond the
1044-
first and third quartiles. In other words, where IQR is the
1045-
interquartile range (`Q3-Q1`), the upper whisker will extend to last
1046-
datum less than `Q3 + whis*IQR`. Similarly, the lower whisker will
1047-
extend to the first datum greater than `Q1 - whis*IQR`.
1048-
Beyond the whiskers, data are considered outliers
1049-
and are plotted as individual points. This can be set to an
1050-
ascending sequence of percentiles (e.g., [5, 95]) to set the
1051-
whiskers at specific percentiles of the data. Finally, `whis`
1052-
can be the string ``'range'`` to force the whiskers to the
1053-
minimum and maximum of the data. In the edge case that the 25th
1054-
and 75th percentiles are equivalent, `whis` can be automatically
1055-
set to ``'range'`` via the `autorange` option.
1042+
whis : float or (float, float) (default = 1.5)
1043+
The position of the whiskers.
1044+
1045+
If a float, the lower whisker is at position ``Q1 - whis*(Q3-Q1)``, and
1046+
the upper whisker at position ``Q3 + whis*(Q3-Q1)``, where Q1 and Q3
1047+
are the first and third quartiles.
1048+
1049+
If a pair of floats, they indicate the percentiles at which to draw the
1050+
whiskers (e.g., (5, 95)). In particular, setting this to (0, 100)
1051+
results in whiskers covering the whole range of the data. "range" is
1052+
a deprecated synonym for [0, 100].
1053+
1054+
In the edge case where ``Q1 == Q3``, *whis* is automatically set to
1055+
[0, 100] (cover the whole range of the data) if *autorange* is True.
1056+
1057+
Beyond the whiskers, data are considered outliers and are plotted as
1058+
individual points.
10561059
10571060
bootstrap : int, optional
10581061
Number of times the confidence intervals around the median
@@ -1064,7 +1067,7 @@ def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None,
10641067
10651068
autorange : bool, optional (False)
10661069
When `True` and the data are distributed such that the 25th and 75th
1067-
percentiles are equal, ``whis`` is set to ``'range'`` such that the
1070+
percentiles are equal, ``whis`` is set to (0, 100) such that the
10681071
whisker ends are at the minimum and maximum of the data.
10691072
10701073
Returns
@@ -1182,7 +1185,7 @@ def _compute_conf_interval(data, med, iqr, bootstrap):
11821185
# interquartile range
11831186
stats['iqr'] = q3 - q1
11841187
if stats['iqr'] == 0 and autorange:
1185-
whis = 'range'
1188+
whis = (0, 100)
11861189

11871190
# conf. interval around median
11881191
stats['cilo'], stats['cihi'] = _compute_conf_interval(
@@ -1195,14 +1198,17 @@ def _compute_conf_interval(data, med, iqr, bootstrap):
11951198
loval = q1 - whis * stats['iqr']
11961199
hival = q3 + whis * stats['iqr']
11971200
elif whis in ['range', 'limit', 'limits', 'min/max']:
1201+
warn_deprecated(
1202+
"3.2", message=f"Setting whis to {whis!r} is deprecated "
1203+
"since %(since)s and support for it will be removed "
1204+
"%(removal)s; set it to [0, 100] to achieve the same "
1205+
"effect.")
11981206
loval = np.min(x)
11991207
hival = np.max(x)
12001208
else:
1201-
raise ValueError('whis must be a float, valid string, or list '
1202-
'of percentiles')
1209+
raise ValueError('whis must be a float or list of percentiles')
12031210
else:
1204-
loval = np.percentile(x, whis[0])
1205-
hival = np.percentile(x, whis[1])
1211+
loval, hival = np.percentile(x, whis)
12061212

12071213
# get high extreme
12081214
wiskhi = x[x <= hival]

lib/matplotlib/rcsetup.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,6 +503,10 @@ def validate_verbose(s):
503503

504504
def validate_whiskers(s):
505505
if s == 'range':
506+
cbook.warn_deprecated(
507+
"3.2", message="Support for setting the boxplot.whiskers rcParam "
508+
"to 'range' is deprecated since %(since)s and will be removed "
509+
"%(removal)s; set it to 0, 100 instead.")
506510
return 'range'
507511
else:
508512
try:

lib/matplotlib/tests/test_axes.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,7 +2182,7 @@ def test_bxp_baseline():
21822182
savefig_kwarg={'dpi': 40},
21832183
style='default')
21842184
def test_bxp_rangewhis():
2185-
_bxp_test_helper(stats_kwargs=dict(whis='range'))
2185+
_bxp_test_helper(stats_kwargs=dict(whis=[0, 100]))
21862186

21872187

21882188
@image_comparison(['bxp_precentilewhis.png'],
@@ -2500,7 +2500,7 @@ def test_boxplot_rc_parameters():
25002500

25012501
rc_axis1 = {
25022502
'boxplot.vertical': False,
2503-
'boxplot.whiskers': 'range',
2503+
'boxplot.whiskers': [0, 100],
25042504
'boxplot.patchartist': True,
25052505
}
25062506

lib/matplotlib/tests/test_cbook.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def test_results_whiskers_float(self):
147147
assert_array_almost_equal(res[key], value)
148148

149149
def test_results_whiskers_range(self):
150-
results = cbook.boxplot_stats(self.data, whis='range')
150+
results = cbook.boxplot_stats(self.data, whis=[0, 100])
151151
res = results[0]
152152
for key, value in self.known_res_range.items():
153153
assert_array_almost_equal(res[key], value)

0 commit comments

Comments
 (0)