From a62c25f630af24e3226c3457c4ecb8bee4d0f69f Mon Sep 17 00:00:00 2001 From: saranti Date: Tue, 26 Dec 2023 17:11:19 +1100 Subject: [PATCH 1/2] fix boxplot legend entries --- lib/matplotlib/axes/_axes.py | 7 +++++++ lib/matplotlib/tests/test_legend.py | 32 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index ef7d3edfa0b9..b1aeb87e6b45 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -4004,6 +4004,9 @@ 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 @@ -4316,13 +4319,16 @@ def do_patch(xs, ys, **kwargs): do_box = do_patch if patch_artist else do_plot boxes.append(do_box(box_x, box_y, **box_kw)) # draw the whiskers + whisker_kw.setdefault('label', '_nolegend_') whiskers.append(do_plot(whis_x, whislo_y, **whisker_kw)) whiskers.append(do_plot(whis_x, whishi_y, **whisker_kw)) # maybe draw the caps if showcaps: + cap_kw.setdefault('label', '_nolegend_') caps.append(do_plot(cap_x, cap_lo, **cap_kw)) caps.append(do_plot(cap_x, cap_hi, **cap_kw)) # draw the medians + median_kw.setdefault('label', '_nolegend_') medians.append(do_plot(med_x, med_y, **median_kw)) # maybe draw the means if showmeans: @@ -4335,6 +4341,7 @@ def do_patch(xs, ys, **kwargs): means.append(do_plot([pos], [stats['mean']], **mean_kw)) # maybe draw the fliers if showfliers: + flier_kw.setdefault('label', '_nolegend_') flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64) flier_y = stats['fliers'] fliers.append(do_plot(flier_x, flier_y, **flier_kw)) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 1cc8f535f57e..6357b4ce62a0 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -1427,3 +1427,35 @@ def test_legend_text(): leg_bboxes.append( leg.get_window_extent().transformed(ax.transAxes.inverted())) 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() + index = 0 + for i in legend.legend_handles: + assert isinstance(i, mpl.patches.Rectangle) + assert i.get_facecolor() == colors[index] + assert i.get_edgecolor() == colors[index] + assert i.get_label() == labels[index] + index += 1 From 6ef9cce3ff653de8f1bb8fd5715abbf73841ca70 Mon Sep 17 00:00:00 2001 From: saranti Date: Wed, 31 Jan 2024 13:14:02 +1100 Subject: [PATCH 2/2] improve test code --- lib/matplotlib/tests/test_legend.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/tests/test_legend.py b/lib/matplotlib/tests/test_legend.py index 6357b4ce62a0..820f9d967f24 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -1452,10 +1452,8 @@ def test_boxplot_legend(): lbl_index += 1 legend = axs.legend() - index = 0 - for i in legend.legend_handles: - assert isinstance(i, mpl.patches.Rectangle) - assert i.get_facecolor() == colors[index] - assert i.get_edgecolor() == colors[index] - assert i.get_label() == labels[index] - index += 1 + 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]