Skip to content

Adding density hist2d #12563

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -6780,8 +6780,8 @@ def hist(self, x, bins=None, range=None, density=None, weights=None,
return tops, bins, cbook.silent_list('Lists of Patches', patches)

@_preprocess_data(replace_names=["x", "y", "weights"], label_namer=None)
def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None,
cmin=None, cmax=None, **kwargs):
def hist2d(self, x, y, bins=10, range=None, density=None, weights=None,
cmin=None, cmax=None, normed=None, **kwargs):
"""
Make a 2D histogram plot.

Expand Down Expand Up @@ -6814,8 +6814,14 @@ def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None,
xmax], [ymin, ymax]]``. All values outside of this range will be
considered outliers and not tallied in the histogram.

normed : bool, optional, default: False
Normalize histogram.
density : boolean, optional
If False, the default, plots and returns the number of samples
in each bin. If True, returns the probability *density*
function at the bin, ``bin_count / sample_count / bin_area``.
Default is ``None`` for both *normed* and *density*. If either is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep the discussion of deprecated normed kwarg in the description of that kwarg?

set, then that value will be used. If neither are set, then the
args will be treated as ``False``.
If both *density* and *normed* are set an error is raised.

weights : array_like, shape (n, ), optional, default: None
An array of values w_i weighing each sample (x_i, y_i).
Expand All @@ -6830,6 +6836,12 @@ def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None,
to none before passing to imshow) and these count values in the
return value count histogram will also be set to nan upon return

normed : bool, optional, default: None
Deprecated; use the density keyword argument instead.
Numpy 1.15 introduced a 'density' kwarg to ``hist2d``. Even though
Numpy 1.15 isn't required, 'density' kwarg is introduced
and passed as 'normed' to ``hist2d``.

Returns
-------
h : 2D array
Expand Down Expand Up @@ -6873,8 +6885,17 @@ def hist2d(self, x, y, bins=10, range=None, normed=False, weights=None,
`.colors.PowerNorm`.
"""

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' is deprecated.")
if normed is not None:
cbook.warn_deprecated("3.1", name="'normed'", obj_type="kwarg",
alternative="'density")

density = bool(density) or bool(normed)
h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should call the argument normed if we are going to change to density later.

This could also use a comment in here about how we will need to switch to density when np1.15 becomes our minimal version. Otherwise if I was looking at this code I'd have no idea why you are deprecating the name normed when that's what numpy is using. Indeed reviewing this I had to see @anntzer 's comment: #11070 (comment) to understand why you were doing this. Should probably be in the PR description as well to save folks back referencing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the comments. I was trying to be consistent with hist. #11070 was opened to have API consistency. I can also change hist to be consistent with your suggestions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with the change proposed here , but only because numpy is moving to using density as well (in np1.15). So the PR should be clear why we are doing this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you still have normed = bool(density) or bool(normed), I think you should be populating and using density not normed.

I think there should be a comment in the code here for future reference to explain this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I misunderstood about your comment on density. Let me fix it right away.

normed=normed, weights=weights)
normed=density, weights=weights)

if cmin is not None:
h[h < cmin] = None
Expand Down
10 changes: 5 additions & 5 deletions lib/matplotlib/pyplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2640,12 +2640,12 @@ def hist(
# Autogenerated by boilerplate.py. Do not edit as changes will be lost.
@_autogen_docstring(Axes.hist2d)
def hist2d(
x, y, bins=10, range=None, normed=False, weights=None,
cmin=None, cmax=None, *, data=None, **kwargs):
x, y, bins=10, range=None, density=None, weights=None,
cmin=None, cmax=None, normed=None, *, data=None, **kwargs):
__ret = gca().hist2d(
x, y, bins=bins, range=range, normed=normed, weights=weights,
cmin=cmin, cmax=cmax, **({"data": data} if data is not None
else {}), **kwargs)
x, y, bins=bins, range=range, density=density,
weights=weights, cmin=cmin, cmax=cmax, normed=normed,
**({"data": data} if data is not None else {}), **kwargs)
sci(__ret[-1])
return __ret

Expand Down
24 changes: 24 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1672,6 +1672,30 @@ def test_hist2d():
ax.hist2d("x", "y", bins=10, data=data, rasterized=True)


@pytest.mark.parametrize('density', [False, True])
def test_hist2d_density(density):
# Test density kwarg
x = np.random.randn(100)*2+5
y = np.random.randn(100)-2
fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist2d(x, y, bins=10, rasterized=True, density=density)


@pytest.mark.parametrize('normed', [False, True])
@pytest.mark.parametrize('density', [False, True])
def test_hist2d_normed_density(density, normed):
# Normed and density should not be used simultaneously
x = np.random.randn(100)*2+5
y = np.random.randn(100)-2
fig = plt.figure()
ax = fig.add_subplot(111)
# test that kwargs normed and density cannot be set both.
with pytest.raises(ValueError, match="kwargs 'density' and 'normed'"):
ax.hist2d(x, y, bins=10, rasterized=True,
density=density, normed=normed)


@image_comparison(baseline_images=['hist2d_transpose'],
remove_text=True, style='mpl20')
def test_hist2d_transpose():
Expand Down