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..820f9d967f24 100644 --- a/lib/matplotlib/tests/test_legend.py +++ b/lib/matplotlib/tests/test_legend.py @@ -1427,3 +1427,33 @@ 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() + 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]