diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 13f73028ff0f..4d052dce08ae 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -92,7 +92,6 @@ def _plot_args_replacer(args, data): # The axes module contains all the wrappers to plotting functions. # All the other methods should go in the _AxesBase class. - class Axes(_AxesBase): """ The :class:`Axes` contains most of the figure elements: @@ -5911,9 +5910,9 @@ def table(self, **kwargs): #### Data analysis @_preprocess_data(replace_names=["x", 'weights'], label_namer="x") - def hist(self, x, bins=None, range=None, normed=False, weights=None, - cumulative=False, bottom=None, histtype='bar', align='mid', - orientation='vertical', rwidth=None, log=False, + def hist(self, x, bins=None, range=None, density=None, normed=None, + weights=None, cumulative=False, bottom=None, histtype='bar', + align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, **kwargs): """ @@ -5959,7 +5958,7 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, Default is ``None`` - normed : boolean, optional + density : boolean, optional If `True`, the first element of the return tuple will be the counts normalized to form a probability density, i.e., the area (or integral) under the histogram will sum to 1. @@ -5968,7 +5967,11 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, of observations. If `stacked` is also `True`, the sum of the histograms is normalized to 1. - Default is ``False`` + Default is ``None``, behaves as ``False``. + + normed : boolean, optional + Will be deprecated, same role as density. For consistency + with NumPy 2.0.0 keyword density has been introduced. weights : (n, ) array_like or None, optional An array of weights, of the same shape as `x`. Each value in `x` @@ -6132,6 +6135,11 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, if histtype == 'barstacked' and not stacked: stacked = True + if density is not None and normed is not None: + raise ValueError("kwargs 'density' and 'normed' cannot be used" + "simultaneously. Please only use 'density', since " + "'normed' will be deprecated. ") + # process the unit information self._process_unit_info(xdata=x, kwargs=kwargs) x = self.convert_xunits(x) @@ -6186,11 +6194,11 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, xmin = min(xmin, xi.min()) xmax = max(xmax, xi.max()) bin_range = (xmin, xmax) - - # hist_kwargs = dict(range=range, normed=bool(normed)) - # We will handle the normed kwarg within mpl until we - # get to the point of requiring numpy >= 1.5. - hist_kwargs = dict(range=bin_range) + density = bool(density) or bool(normed) + if density and not stacked: + hist_kwargs = dict(range=bin_range, density=density) + else: + hist_kwargs = dict(range=bin_range) n = [] mlast = None @@ -6201,9 +6209,7 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, m = m.astype(float) # causes problems later if it's an int if mlast is None: mlast = np.zeros(len(bins)-1, m.dtype) - if normed and not stacked: - db = np.diff(bins) - m = (m.astype(float) / db) / m.sum() + if stacked: if mlast is None: mlast = np.zeros(len(bins)-1, m.dtype) @@ -6211,7 +6217,7 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, mlast[:] = m n.append(m) - if stacked and normed: + if stacked and density: db = np.diff(bins) for m in n: m[:] = (m.astype(float) / db) / n[-1].sum() @@ -6220,7 +6226,7 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, if cbook.is_numlike(cumulative) and cumulative < 0: slc = slice(None, None, -1) - if normed: + if density: n = [(m * np.diff(bins))[slc].cumsum()[slc] for m in n] else: n = [m[slc].cumsum()[slc] for m in n] @@ -6307,13 +6313,14 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None, # Setting a minimum of 0 results in problems for log plots if np.min(bottom) > 0: minimum = np.min(bottom) - elif normed or weights is not None: - # For normed data, set to minimum data value / logbase - # (gives 1 full tick-label unit for the lowest filled bin) + elif density or weights is not None: + # For normed (density = True) data full tick-label unit + # for the lowest filled bin) ndata = np.array(n) minimum = (np.min(ndata[ndata > 0])) / logbase else: - # For non-normed data, set the min to 1 / log base, + # For non-normed (density = False) data, + # set the min to 1 / log base, # again so that there is 1 full tick-label unit # for the lowest bin minimum = 1.0 / logbase diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py index 3a8f70f761b6..26fbef408697 100644 --- a/lib/matplotlib/pyplot.py +++ b/lib/matplotlib/pyplot.py @@ -2991,10 +2991,10 @@ def hexbin(x, y, C=None, gridsize=100, bins=None, xscale='linear', # This function was autogenerated by boilerplate.py. Do not edit as # changes will be lost @_autogen_docstring(Axes.hist) -def hist(x, bins=None, range=None, normed=False, weights=None, cumulative=False, - bottom=None, histtype='bar', align='mid', orientation='vertical', - rwidth=None, log=False, color=None, label=None, stacked=False, - hold=None, data=None, **kwargs): +def hist(x, bins=None, range=None, density=None, normed=None, weights=None, + cumulative=False, bottom=None, histtype='bar', align='mid', + orientation='vertical', rwidth=None, log=False, color=None, label=None, + stacked=False, hold=None, data=None, **kwargs): ax = gca() # Deprecated: allow callers to override the hold state # by passing hold=True|False @@ -3006,11 +3006,12 @@ def hist(x, bins=None, range=None, normed=False, weights=None, cumulative=False, warnings.warn("The 'hold' keyword argument is deprecated since 2.0.", mplDeprecation) try: - ret = ax.hist(x, bins=bins, range=range, normed=normed, - weights=weights, cumulative=cumulative, bottom=bottom, - histtype=histtype, align=align, orientation=orientation, - rwidth=rwidth, log=log, color=color, label=label, - stacked=stacked, data=data, **kwargs) + ret = ax.hist(x, bins=bins, range=range, density=density, + normed=normed, weights=weights, cumulative=cumulative, + bottom=bottom, histtype=histtype, align=align, + orientation=orientation, rwidth=rwidth, log=log, + color=color, label=label, stacked=stacked, data=data, + **kwargs) finally: ax._hold = washold diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 4ffdf72c8c65..393f1ae22bbe 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -2698,6 +2698,36 @@ def test_hist_stacked_normed(): ax = fig.add_subplot(111) ax.hist((d1, d2), stacked=True, normed=True) +@image_comparison(baseline_images=['hist_stacked_normed']) +def test_hist_stacked_density(): + # make some data + d1 = np.linspace(1, 3, 20) + d2 = np.linspace(0, 10, 50) + fig = plt.figure() + ax = fig.add_subplot(111) + ax.hist((d1, d2), stacked=True, density=True) + + +def test_hist_normed_density(): + #Normed and density should not be used simultaneously + d1 = np.linspace(1, 3, 20) + d2 = np.linspace(0, 10, 50) + fig = plt.figure() + ax = fig.add_subplot(111) + #test that kwargs normed and density cannot be set both. + with pytest.raises(Exception): + ax.hist((d1, d2), stacked=True, normed=True, density=True) + + with pytest.raises(Exception): + ax.hist((d1, d2), stacked=True, normed=False, density=True) + + with pytest.raises(Exception): + ax.hist((d1, d2), stacked=True, normed=False, density=False) + + with pytest.raises(Exception): + ax.hist((d1, d2), stacked=True, normed=True, density=False) + + @image_comparison(baseline_images=['hist_step_bottom'], extensions=['png'], remove_text=True)