Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit eca1f25

Browse filesBrowse files
committed
stop multiple, identical legend entries being created + cleanup
1 parent cde0248 commit eca1f25
Copy full SHA for eca1f25

File tree

Expand file treeCollapse file tree

3 files changed

+34
-21
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+34
-21
lines changed

‎doc/users/next_whats_new/boxplot_legend_support.rst

Copy file name to clipboardExpand all lines: doc/users/next_whats_new/boxplot_legend_support.rst
+5-4Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
Legend support for Boxplot
22
~~~~~~~~~~~~~~~~~~~~~~~~~~
3-
Boxplots now generate legend entries and can be labelled with the
4-
new *label* parameter. If a patch is passed to the box with ``patch_artist=True``,
5-
the legend gets its handle from the patch instead of the `.Line2D` object from
6-
the medians.
3+
Boxplots now support a *label* parameter to create legend entries.
4+
Legend labels can be passed as a string to each individual boxplot
5+
or as a list of strings to label multiple boxes in a single
6+
boxplot call.
7+
78

89
.. plot::
910
:include-source: true

‎lib/matplotlib/axes/_axes.py

Copy file name to clipboardExpand all lines: lib/matplotlib/axes/_axes.py
+12-6Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4409,15 +4409,21 @@ def do_patch(xs, ys, **kwargs):
44094409
# Set legend labels
44104410
if label:
44114411
box_or_med = boxes if showbox else medians
4412-
if len(box_or_med) == len(label):
4413-
for index, element in enumerate(box_or_med):
4414-
if cbook.is_scalar_or_string(label):
4412+
for index, element in enumerate(box_or_med):
4413+
if cbook.is_scalar_or_string(label):
4414+
# If there are multiple boxes, the label
4415+
# should only be applied to the first box.
4416+
if len(box_or_med) > len(label):
44154417
element.set_label(label)
4418+
break
44164419
else:
4420+
element.set_label(label)
4421+
else: # label is a sequence
4422+
if len(box_or_med) == len(label):
44174423
element.set_label(label[index])
4418-
else:
4419-
raise ValueError("There must be an equal number of labels "
4420-
"and plots.")
4424+
else:
4425+
raise ValueError("There must be an equal number of legend"
4426+
" labels and boxplots.")
44214427

44224428
if manage_ticks:
44234429
axis_name = "x" if vert else "y"

‎lib/matplotlib/tests/test_legend.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_legend.py
+17-11Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,29 +1453,35 @@ def test_boxplot_labels():
14531453

14541454

14551455
def test_boxplot_legend_labels():
1456-
# Test that legend entries are generated from boxplots. `label` is the new
1457-
# parameter for setting legend labels.
1456+
# Test that legend entries are generated when passing `label`.
14581457
np.random.seed(19680801)
14591458
data = np.random.random((10, 4))
1460-
fig, axs = plt.subplots(nrows=1, ncols=3)
1459+
fig, axs = plt.subplots(nrows=1, ncols=4)
1460+
legend_labels = ['A', 'B', 'C', 'D']
14611461

14621462
# Testing legend labels and patch passed to legend.
1463-
bp1 = axs[0].boxplot(data, patch_artist=True, label=['A', 'B', 'C', 'D'])
1463+
bp1 = axs[0].boxplot(data, patch_artist=True, label=legend_labels)
14641464
for i, v in enumerate(bp1['boxes']):
1465-
assert v.get_label() == ['A', 'B', 'C', 'D'][i]
1465+
assert v.get_label() == legend_labels[i]
14661466
handles, labels = axs[0].get_legend_handles_labels()
1467-
assert labels == ['A', 'B', 'C', 'D']
1467+
assert labels == legend_labels
14681468
assert all(isinstance(h, mpl.patches.PathPatch) for h in handles)
14691469

14701470
# Testing legend without `box`.
1471-
bp2 = axs[1].boxplot(data, label=['A', 'B', 'C', 'D'], showbox=False)
1471+
bp2 = axs[1].boxplot(data, label=legend_labels, showbox=False)
14721472
# Without a box, The legend entries should be passed from the medians.
14731473
for i, v in enumerate(bp2['medians']):
1474-
assert v.get_label() == ['A', 'B', 'C', 'D'][i]
1474+
assert v.get_label() == legend_labels[i]
14751475
handles, labels = axs[1].get_legend_handles_labels()
1476-
assert labels == ['A', 'B', 'C', 'D']
1476+
assert labels == legend_labels
14771477
assert all(isinstance(h, mpl.lines.Line2D) for h in handles)
14781478

1479-
# Testing legend with an odd number of labels set.
1479+
# Testing legend with number of labels different from number of boxes.
14801480
with pytest.raises(ValueError, match='There must be an equal number'):
1481-
bp3 = axs[2].boxplot(data, patch_artist=True, label=['A', 'B', 'C'])
1481+
bp3 = axs[2].boxplot(data, label=legend_labels[:-1])
1482+
1483+
# Of 3 identical boxes, test that only the first box gets a label.
1484+
new_data = np.random.random((100, 3))
1485+
bp4 = axs[3].boxplot(new_data, label='A')
1486+
assert bp4['boxes'][0].get_label() == 'A' and all(x.get_label() != 'A'
1487+
for x in bp4['boxes'][1:])

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.