diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 5369eadbdefd..9531aa09df51 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4847,8 +4847,8 @@ def hexbin(self, x, y, C=None, gridsize=100, bins=None, yscale : {'linear', 'log'}, default: 'linear' Use a linear or log10 scale on the vertical axis. - mincnt : int > 0, default: *None* - If not *None*, only display cells with more than *mincnt* + mincnt : int >= 0, default: *None* + If not *None*, only display cells with at least *mincnt* number of points in the cell. marginals : bool, default: *False* @@ -5012,9 +5012,10 @@ def reduce_C_function(C: array) -> float else: Cs_at_i2[i2[i]].append(C[i]) if mincnt is None: - mincnt = 0 + mincnt = 1 + threshold = max(mincnt, 1) accum = np.array( - [reduce_C_function(acc) if len(acc) > mincnt else np.nan + [reduce_C_function(acc) if len(acc) >= threshold else np.nan for Cs_at_i in [Cs_at_i1, Cs_at_i2] for acc in Cs_at_i[1:]], # [1:] drops out-of-range points. float) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 065d17f953cb..d2a3914179ae 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -999,6 +999,58 @@ def test_hexbin_log_clim(): assert h.get_clim() == (2, 100) +def test_hexbin_mincnt_counts(): + x = np.array([0.1, 1.6]) + y = np.array([0.1, 1.6]) + fig, ax = plt.subplots() + coll = ax.hexbin( + x, y, gridsize=(2, 2), extent=(0, 2, 0, 2), mincnt=1) + assert_array_equal(coll.get_array(), np.array([1.0, 1.0])) + + +def test_hexbin_mincnt_with_C(): + x = np.array([0.1, 1.6]) + y = np.array([0.1, 1.6]) + fig, ax = plt.subplots() + coll = ax.hexbin( + x, y, C=np.ones_like(x), gridsize=(2, 2), extent=(0, 2, 0, 2), + mincnt=1, reduce_C_function=np.sum) + assert_array_equal(coll.get_array(), np.array([1.0, 1.0])) + + +def test_hexbin_mincnt_excludes_when_below_threshold(): + x = np.array([0.1, 1.6]) + y = np.array([0.1, 1.6]) + fig, ax = plt.subplots() + counts = ax.hexbin( + x, y, gridsize=(2, 2), extent=(0, 2, 0, 2), mincnt=2) + assert len(counts.get_array()) == 0 + + fig, ax = plt.subplots() + reduced = ax.hexbin( + x, y, C=np.ones_like(x), gridsize=(2, 2), extent=(0, 2, 0, 2), + mincnt=2, reduce_C_function=np.sum) + assert len(reduced.get_array()) == 0 + + +def test_hexbin_mincnt_zero_with_C_matches_default(): + x = np.array([0.1, 1.6]) + y = np.array([0.1, 1.6]) + fig, ax = plt.subplots() + hb_zero = ax.hexbin( + x, y, C=np.ones_like(x), gridsize=(3, 3), extent=(0, 2, 0, 2), + mincnt=0, reduce_C_function=np.sum) + + fig, ax = plt.subplots() + hb_default = ax.hexbin( + x, y, C=np.ones_like(x), gridsize=(3, 3), extent=(0, 2, 0, 2), + reduce_C_function=np.sum) + + assert_array_equal(hb_zero.get_offsets(), hb_default.get_offsets()) + assert_array_equal(hb_zero.get_array(), hb_default.get_array()) + assert len(hb_zero.get_array()) == 2 + + def test_inverted_limits(): # Test gh:1553 # Calling invert_xaxis prior to plotting should not disable autoscaling