36
36
from matplotlib .axes ._base import _AxesBase , _process_plot_format
37
37
from matplotlib .axes ._secondary_axes import SecondaryAxis
38
38
39
+ try :
40
+ from numpy .lib .histograms import histogram_bin_edges
41
+ except ImportError :
42
+ # this function is new in np 1.15
43
+ def histogram_bin_edges (arr , bins , range = None , weights = None ):
44
+ # this in True for 1D arrays, and False for None and str
45
+ if np .ndim (bins ) == 1 :
46
+ return bins
47
+
48
+ if isinstance (bins , str ):
49
+ # rather than backporting the internals, just do the full
50
+ # computation. If this is too slow for users, they can
51
+ # update numpy, or pick a manual number of bins
52
+ return np .histogram (arr , bins , range , weights )[1 ]
53
+ else :
54
+ if bins is None :
55
+ # hard-code numpy's default
56
+ bins = 10
57
+ if range is None :
58
+ range = np .min (arr ), np .max (arr )
59
+
60
+ return np .linspace (* range , bins + 1 )
61
+
62
+
39
63
_log = logging .getLogger (__name__ )
40
64
41
65
@@ -6611,9 +6635,6 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
6611
6635
if bin_range is not None :
6612
6636
bin_range = self .convert_xunits (bin_range )
6613
6637
6614
- # Check whether bins or range are given explicitly.
6615
- binsgiven = np .iterable (bins ) or bin_range is not None
6616
-
6617
6638
# We need to do to 'weights' what was done to 'x'
6618
6639
if weights is not None :
6619
6640
w = cbook ._reshape_2D (weights , 'weights' )
@@ -6638,22 +6659,42 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
6638
6659
"sets and %d colors were provided" % (nx , len (color )))
6639
6660
raise ValueError (error_message )
6640
6661
6641
- # If bins are not specified either explicitly or via range,
6642
- # we need to figure out the range required for all datasets,
6643
- # and supply that to np.histogram.
6644
- if not binsgiven and not input_empty :
6662
+ hist_kwargs = dict ()
6663
+
6664
+ # if the bin_range is not given, compute without nan numpy
6665
+ # does not do this for us when guessing the range (but will
6666
+ # happily ignore nans when computing the histogram).
6667
+ if bin_range is None :
6645
6668
xmin = np .inf
6646
6669
xmax = - np .inf
6647
6670
for xi in x :
6648
- if len (xi ) > 0 :
6671
+ if len (xi ):
6672
+ # python's min/max ignore nan,
6673
+ # np.minnan returns nan for all nan input
6649
6674
xmin = min (xmin , np .nanmin (xi ))
6650
6675
xmax = max (xmax , np .nanmax (xi ))
6651
- bin_range = (xmin , xmax )
6676
+ # make sure we have seen at least one non-nan and finite
6677
+ # value before we reset the bin range
6678
+ if not np .isnan ([xmin , xmax ]).any () and not (xmin > xmax ):
6679
+ bin_range = (xmin , xmax )
6680
+
6681
+ # If bins are not specified either explicitly or via range,
6682
+ # we need to figure out the range required for all datasets,
6683
+ # and supply that to np.histogram.
6684
+ if not input_empty and len (x ) > 1 :
6685
+ if weights is not None :
6686
+ _w = np .concatenate (w )
6687
+ else :
6688
+ _w = None
6689
+
6690
+ bins = histogram_bin_edges (np .concatenate (x ),
6691
+ bins , bin_range , _w )
6692
+ else :
6693
+ hist_kwargs ['range' ] = bin_range
6694
+
6652
6695
density = bool (density ) or bool (normed )
6653
6696
if density and not stacked :
6654
- hist_kwargs = dict (range = bin_range , density = density )
6655
- else :
6656
- hist_kwargs = dict (range = bin_range )
6697
+ hist_kwargs = dict (density = density )
6657
6698
6658
6699
# List to store all the top coordinates of the histograms
6659
6700
tops = []
0 commit comments