From 3dfcb519887a9f24de6fdee9ce7d60ff5ca888de Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:05:59 +0100 Subject: [PATCH] Partly revert #27711 This PR removes the propagation of `labels` to any artist legend labels. Other than the rest of the plotting functions `labels` is not used for legend labels but for xtick labels. This is only poorly documented via https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.bxp.html and in an [example](https://matplotlib.org/stable/gallery/statistics/boxplot_color.html). Whatever our way forward regarding the use of `labels` is, we should by no means propagate them simultaneously to xticks and legend entries. This coupling would cripple users' configurability and limit our ability to migrate to a clear API where legend labels and tick labels can be configured independently. Until we have sorted out a better API, the recommended solution for the original issue #20512 is to grab the artists returned from `boxplot()` and either `set_label()` on them or pass them to the legend call `ax.legend(handles, labels)`. --- lib/matplotlib/axes/_axes.py | 6 ++--- lib/matplotlib/tests/test_legend.py | 41 +++++++++-------------------- 2 files changed, 15 insertions(+), 32 deletions(-) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index b1aeb87e6b45..9eaf2dc331ed 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -3885,7 +3885,8 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, boxes are drawn with Patch artists. labels : sequence, optional - Labels for each dataset (one per dataset). + Labels for each dataset (one per dataset). These are used for + x-tick labels; *not* for legend entries. manage_ticks : bool, default: True If True, the tick locations and labels will be adjusted to match @@ -4004,9 +4005,6 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None, if 'color' in boxprops: boxprops['edgecolor'] = boxprops.pop('color') - if labels: - boxprops['label'] = labels - # if non-default sym value, put it into the flier dictionary # the logic for providing the default symbol ('b+') now lives # in bxp in the initial value of flierkw diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 820f9d967f24..b23649f22e48 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -1429,31 +1429,16 @@ def test_legend_text(): assert_allclose(leg_bboxes[1].bounds, leg_bboxes[0].bounds) -def test_boxplot_legend(): - # Test that boxplot legends handles are patches - # and labels are generated from boxplot's labels parameter. - fig, axs = plt.subplots() - A = 5*np.random.rand(100, 1) - B = 10*np.random.rand(100, 1) - 5 - C = 7*np.random.rand(100, 1) - 5 - labels = ['a', 'b', 'c'] - - bp0 = axs.boxplot(A, positions=[0], patch_artist=True, labels=labels[0]) - bp1 = axs.boxplot(B, positions=[1], patch_artist=True, labels=labels[1]) - bp2 = axs.boxplot(C, positions=[2], patch_artist=True, labels=labels[2]) - # red, blue, green - colors = [(1.0, 0.0, 0.0, 1), (0.0, 0.0, 1.0, 1), (0.0, 0.5, 0.0, 1)] - box_list = [bp0, bp1, bp2] - # Set colors to the boxes - lbl_index = 0 - for b_plot, color in zip(box_list, colors): - for patch in b_plot['boxes']: - patch.set_color(color) - lbl_index += 1 - - legend = axs.legend() - for index, handle in enumerate(legend.legend_handles): - assert isinstance(handle, mpl.patches.Rectangle) - assert handle.get_facecolor() == colors[index] - assert handle.get_edgecolor() == colors[index] - assert handle.get_label() == labels[index] +def test_boxplot_labels(): + # Test that boxplot(..., labels=) sets the tick labels but not legend entries + # This is not consistent with other plot types but is the current behavior. + fig, ax = plt.subplots() + np.random.seed(19680801) + data = np.random.random((10, 3)) + bp = ax.boxplot(data, labels=['A', 'B', 'C']) + # Check that labels set the tick labels ... + assert [l.get_text() for l in ax.get_xticklabels()] == ['A', 'B', 'C'] + # ... but not legend entries + handles, labels = ax.get_legend_handles_labels() + assert len(handles) == 0 + assert len(labels) == 0
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: