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

Skip to content

Commit d7c478b

Browse files
committed
Merge pull request #6187 from jenshnielsen/merge152x
Merge 1.5 into 2x.
2 parents c9c8b8a + 35a1cc8 commit d7c478b

21 files changed

+374
-567
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Changed default ``autorange`` behavior in boxplots
2+
``````````````````````````````````````````````````
3+
4+
Prior to v1.5.2, the whiskers of boxplots would extend to the mininum
5+
and maximum values if the quartiles were all equal (i.e., Q1 = median
6+
= Q3). This behavior has been disabled by default to restore consistency
7+
with other plotting packages.
8+
9+
To restore the old behavior, simply set ``autorange=True`` when
10+
calling ``plt.boxplot``.

lib/matplotlib/animation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -755,8 +755,8 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
755755
# Re-use the savefig DPI for ours if none is given
756756
if dpi is None:
757757
dpi = rcParams['savefig.dpi']
758-
if dpi == 'figure':
759-
dpi = self._fig.dpi
758+
if dpi == 'figure':
759+
dpi = self._fig.dpi
760760

761761
if codec is None:
762762
codec = rcParams['animation.codec']

lib/matplotlib/axes/_axes.py

Lines changed: 143 additions & 136 deletions
Large diffs are not rendered by default.

lib/matplotlib/backend_bases.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,8 +2141,8 @@ def print_figure(self, filename, dpi=None, facecolor='w', edgecolor='w',
21412141

21422142
if dpi is None:
21432143
dpi = rcParams['savefig.dpi']
2144-
if dpi == 'figure':
2145-
dpi = self.figure.dpi
2144+
if dpi == 'figure':
2145+
dpi = self.figure.dpi
21462146

21472147
origDPI = self.figure.dpi
21482148
origfacecolor = self.figure.get_facecolor()

lib/matplotlib/backends/backend_qt5agg.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ def draw_idle(self):
172172
QtCore.QTimer.singleShot(0, self.__draw_idle_agg)
173173

174174
def __draw_idle_agg(self, *args):
175+
if self.height() < 0 or self.width() < 0:
176+
self._agg_draw_pending = False
177+
return
175178
try:
176179
FigureCanvasAgg.draw(self)
177180
self.update()

lib/matplotlib/backends/qt_compat.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,23 @@
4242

4343
QT_API = None
4444

45-
if (QT_API_ENV is not None):
45+
# check if any binding is already imported, if so silently ignore the
46+
# rcparams/ENV settings and use what ever is already imported.
47+
if 'PySide' in sys.modules:
48+
# user has imported PySide before importing mpl
49+
QT_API = QT_API_PYSIDE
50+
51+
if 'PyQt4' in sys.modules:
52+
# user has imported PyQt4 before importing mpl
53+
# this case also handles the PyQt4v2 case as once sip is imported
54+
# the API versions can not be changed so do not try
55+
QT_API = QT_API_PYQT
56+
57+
if 'PyQt5' in sys.modules:
58+
# the user has imported PyQt5 before importing mpl
59+
QT_API = QT_API_PYQT5
60+
61+
if (QT_API_ENV is not None) and QT_API is None:
4662
try:
4763
QT_ENV_MAJOR_VERSION = ETS[QT_API_ENV][1]
4864
except KeyError:
@@ -61,15 +77,12 @@
6177
elif rcParams['backend'] == 'Qt4Agg':
6278
QT_API = rcParams['backend.qt4']
6379
else:
64-
# A different backend was specified, but we still got here because a Qt
65-
# related file was imported. This is allowed, so lets try and guess
66-
# what we should be using.
67-
if "PyQt4" in sys.modules or "PySide" in sys.modules:
68-
# PyQt4 or PySide is actually used.
69-
QT_API = rcParams['backend.qt4']
70-
else:
71-
# This is a fallback: PyQt5
72-
QT_API = rcParams['backend.qt5']
80+
# A non-Qt backend was specified, no version of the Qt
81+
# bindings is imported, but we still got here because a Qt
82+
# related file was imported. This is allowed, fall back to Qt5
83+
# using which ever binding the rparams ask for.
84+
85+
QT_API = rcParams['backend.qt5']
7386

7487
# We will define an appropriate wrapper for the differing versions
7588
# of file dialog.

lib/matplotlib/cbook.py

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,17 @@ def is_sequence_of_strings(obj):
715715
return True
716716

717717

718+
def is_hashable(obj):
719+
"""
720+
Returns true if *obj* can be hashed
721+
"""
722+
try:
723+
hash(obj)
724+
except TypeError:
725+
return False
726+
return True
727+
728+
718729
def is_writable_file_like(obj):
719730
'return true if *obj* looks like a file object with a *write* method'
720731
return hasattr(obj, 'write') and six.callable(obj.write)
@@ -1863,39 +1874,46 @@ def delete_masked_points(*args):
18631874
return margs
18641875

18651876

1866-
def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None):
1867-
'''
1868-
Returns list of dictionaries of staticists to be use to draw a series of
1869-
box and whisker plots. See the `Returns` section below to the required
1870-
keys of the dictionary. Users can skip this function and pass a user-
1871-
defined set of dictionaries to the new `axes.bxp` method instead of
1872-
relying on MPL to do the calcs.
1877+
def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None,
1878+
autorange=False):
1879+
"""
1880+
Returns list of dictionaries of statistics used to draw a series
1881+
of box and whisker plots. The `Returns` section enumerates the
1882+
required keys of the dictionary. Users can skip this function and
1883+
pass a user-defined set of dictionaries to the new `axes.bxp` method
1884+
instead of relying on MPL to do the calculations.
18731885
18741886
Parameters
18751887
----------
18761888
X : array-like
1877-
Data that will be represented in the boxplots. Should have 2 or fewer
1878-
dimensions.
1889+
Data that will be represented in the boxplots. Should have 2 or
1890+
fewer dimensions.
18791891
18801892
whis : float, string, or sequence (default = 1.5)
1881-
As a float, determines the reach of the whiskers past the first and
1882-
third quartiles (e.g., Q3 + whis*IQR, QR = interquartile range, Q3-Q1).
1883-
Beyond the whiskers, data are considered outliers and are plotted as
1884-
individual points. Set this to an unreasonably high value to force the
1885-
whiskers to show the min and max data. Alternatively, set this to an
1886-
ascending sequence of percentile (e.g., [5, 95]) to set the whiskers
1887-
at specific percentiles of the data. Finally, can `whis` be the
1888-
string 'range' to force the whiskers to the min and max of the data.
1889-
In the edge case that the 25th and 75th percentiles are equivalent,
1890-
`whis` will be automatically set to 'range'
1891-
1892-
bootstrap : int or None (default)
1893-
Number of times the confidence intervals around the median should
1894-
be bootstrapped (percentile method).
1895-
1896-
labels : sequence
1897-
Labels for each dataset. Length must be compatible with dimensions
1898-
of `X`
1893+
As a float, determines the reach of the whiskers past the first
1894+
and third quartiles (e.g., Q3 + whis*IQR, QR = interquartile
1895+
range, Q3-Q1). Beyond the whiskers, data are considered outliers
1896+
and are plotted as individual points. This can be set this to an
1897+
ascending sequence of percentile (e.g., [5, 95]) to set the
1898+
whiskers at specific percentiles of the data. Finally, `whis`
1899+
can be the string ``'range'`` to force the whiskers to the
1900+
minimum and maximum of the data. In the edge case that the 25th
1901+
and 75th percentiles are equivalent, `whis` can be automatically
1902+
set to ``'range'`` via the `autorange` option.
1903+
1904+
bootstrap : int, optional
1905+
Number of times the confidence intervals around the median
1906+
should be bootstrapped (percentile method).
1907+
1908+
labels : array-like, optional
1909+
Labels for each dataset. Length must be compatible with
1910+
dimensions of `X`.
1911+
1912+
autorange : bool, optional (False)
1913+
When `True` and the data are distributed such that the 25th and
1914+
75th percentiles are equal, ``whis`` is set to ``'range'`` such
1915+
that the whisker ends are at the minimum and maximum of the
1916+
data.
18991917
19001918
Returns
19011919
-------
@@ -1920,8 +1938,8 @@ def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None):
19201938
19211939
Notes
19221940
-----
1923-
Non-bootstrapping approach to confidence interval uses Gaussian-based
1924-
asymptotic approximation:
1941+
Non-bootstrapping approach to confidence interval uses Gaussian-
1942+
based asymptotic approximation:
19251943
19261944
.. math::
19271945
@@ -1931,7 +1949,7 @@ def boxplot_stats(X, whis=1.5, bootstrap=None, labels=None):
19311949
McGill, R., Tukey, J.W., and Larsen, W.A. (1978) "Variations of
19321950
Boxplots", The American Statistician, 32:12-16.
19331951
1934-
'''
1952+
"""
19351953

19361954
def _bootstrap_median(data, N=5000):
19371955
# determine 95% confidence intervals of the median
@@ -2011,7 +2029,7 @@ def _compute_conf_interval(data, med, iqr, bootstrap):
20112029

20122030
# interquartile range
20132031
stats['iqr'] = q3 - q1
2014-
if stats['iqr'] == 0:
2032+
if stats['iqr'] == 0 and autorange:
20152033
whis = 'range'
20162034

20172035
# conf. interval around median

lib/matplotlib/collections.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def _get_value(val):
151151
except TypeError:
152152
if cbook.iterable(val) and len(val):
153153
try:
154-
float(val[0])
154+
float(cbook.safe_first_element(val))
155155
except (TypeError, ValueError):
156156
pass # raise below
157157
else:
@@ -164,7 +164,7 @@ def _get_bool(val):
164164
if not cbook.iterable(val):
165165
val = (val,)
166166
try:
167-
bool(val[0])
167+
bool(cbook.safe_first_element(val))
168168
except (TypeError, IndexError):
169169
raise TypeError('val must be a bool or nonzero sequence of them')
170170
return val
@@ -532,7 +532,7 @@ def set_linestyle(self, ls):
532532
The line style.
533533
"""
534534
try:
535-
if cbook.is_string_like(ls):
535+
if cbook.is_string_like(ls) and cbook.is_hashable(ls):
536536
ls = cbook.ls_mapper.get(ls, ls)
537537
dashes = [mlines.get_dash_pattern(ls)]
538538
elif cbook.iterable(ls):

lib/matplotlib/colors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,8 @@ def __init__(self, colors, name='from_list', N=None):
821821
if N is None:
822822
N = len(self.colors)
823823
else:
824-
if cbook.is_string_like(self.colors):
824+
if (cbook.is_string_like(self.colors) and
825+
cbook.is_hashable(self.colors)):
825826
self.colors = [self.colors] * N
826827
self.monochrome = True
827828
elif cbook.iterable(self.colors):

lib/matplotlib/figure.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,8 +1508,6 @@ def savefig(self, *args, **kwargs):
15081508
"""
15091509

15101510
kwargs.setdefault('dpi', rcParams['savefig.dpi'])
1511-
if kwargs['dpi'] == 'figure':
1512-
kwargs['dpi'] = self.get_dpi()
15131511
frameon = kwargs.pop('frameon', rcParams['savefig.frameon'])
15141512
transparent = kwargs.pop('transparent',
15151513
rcParams['savefig.transparent'])
Binary file not shown.

0 commit comments

Comments
 (0)