Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Add legend support for boxplots#27840

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
QuLogic merged 5 commits intomatplotlib:mainfromsaranti:box_legend_support
Mar 21, 2024

Conversation

saranti
Copy link
Contributor

@sarantisaranti commentedMar 1, 2024
edited
Loading

PR summary

Closes#27792. Boxplots now get legend entries.
This was previously attempted on#27711 and then reverted#27780 because it used the same parameter for tick labels and didn't generalize well. These 2 issues have been addressed in this PR.

A newlabel parameter has been added toAxes.boxplot andAxes.bxp. If called viaax.boxplot(), label is passed to the bxp function, otherwise bxp can be directly called with the label parameter.

The label is passed to theboxes object ifshowbox=True, otherwise it will be passed to themedians object isshowbox=False. Attaching the label to the boxes makes sure that the legend handles will get a patch which will be displayed on the legend.
If the box is turned off, the legend handles will get a Line2D object from the median line which will be displayed as a line in the legend. This has 2 advantages:

  • It suits the aesthetics of a boxless plot
  • Unlike thebox,caps,flyers andmeans, themedians cannot be turned off so they're a good vehicle for the legend label and will ensure that the labels always get set.
Click to old test cases

new_test

PR checklist

@saranti
Copy link
ContributorAuthor

saranti commentedMar 2, 2024
edited
Loading

Other things that need to be done at some stage:

@sarantisaranti marked this pull request as draftMarch 3, 2024 04:30
@sarantisaranti marked this pull request as ready for reviewMarch 3, 2024 12:09
Copy link
Member

@rcomerrcomer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks for your work on this@saranti. It looks like you've done some good work pulling a variety of strands together.

One thing I'm a bit confused about is how the legend label is passed fromboxplot tobxp. It is passed both as part of theboxprops dictionary and by itself. Why not just pass with thelabel parameter?

saranti reacted with thumbs up emoji
@@ -0,0 +1,5 @@
``boxplot`` legend labels
~~~~~~~~~~~~~~~~~~~~~~~~~
The tick labels on `~.Axes.boxplot` were previously set with the `labels` parameter.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
The tick labels on `~.Axes.boxplot` were previously set with the`labels` parameter.
The tick labels on `~.Axes.boxplot` were previously set with the*labels* parameter.

When you use backticks, Sphinx tries to turn the word into a link. We have a convention to useemphasis for parameters.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

You're right, theboxprops label is redundant. When i first implemented this, I used it as the only check to see iflabels has been set but then I realized that it should've been set at the bxp function. Everything in the 'if boxprops' condition is no longer needed.

Legend support for Boxplot
~~~~~~~~~~~~~~~~~~~~~~~~~~
Boxplots now generate legend entries and can be labelled with the
new `label` parameter. If a patch is passed to the box with `show_patch=True`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
new`label` parameter. If a patch is passed to the box with `show_patch=True`,
new*label* parameter. If a patch is passed to the box with ``show_patch=True``,

Double backtick gets you code formatting.

saranti reacted with thumbs up emoji
@@ -3884,10 +3885,12 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
If `False` produces boxes with the Line2D artist. Otherwise,
boxes are drawn with Patch artists.

labels : sequence, optional
tick_labels : sequence, optional
Labels for each dataset (one per dataset). These are used for
x-tick labels; *not* for legend entries.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Since the parameter now has a more specific name, I think we no longer need the note about them not being for the legend.

saranti reacted with thumbs up emoji
label : sequence, optional
Legend labels for each boxplot.

.. versionadded:: 3.9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

IIRC thedata parameter is special and should always come last.

saranti reacted with thumbs up emoji
box_or_whis = boxes if showbox else whiskers
for index, element in enumerate(box_or_whis):
try:
if isinstance(boxprops['label'], list):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I thinkis_scalar_or_string may be useful here.

saranti reacted with thumbs up emoji
with pytest.warns(mpl.MatplotlibDeprecationWarning,
match='has been renamed \'tick_labels\''):
first = axs[0, 0].boxplot(data,
labels=labels, # `tick_labels`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Maybe usetick_labels here rather than the deprecated name?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

If I don't use the deprecated name then this pytest will fail.


# This plot will not generate a legend.
with pytest.warns(UserWarning, match='No artists with labels found'):
warnings.warn('No artists with labels found.', UserWarning)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think this might be a stray debugging line?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yes it is. I'm having trouble trying to get pytest to catch the UserWarning whenlegend is called without the labels being set. The list of emitted warnings is always null even though the warning is clearly raised in

eliflen(args)==0:# 0 args: automatically detect labels and handles.
handles,labels=_get_legend_handles_labels(axs,handlers)
ifnothandles:
_api.warn_external(
"No artists with labels found to put in legend. Note that "
"artists whose label start with an underscore are ignored "
"when legend() is called with no argument.")

showmeans=True,
patch_artist=True)
axs[0, 1].set_title('Tick labels, no legend')
axs[0, 1].legend()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It might be good for this test toget hold of the legend handles and labels and assert that these lists are empty.

saranti reacted with thumbs up emoji
@@ -3956,6 +3959,10 @@ def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
The style of the mean.
data : indexable object, optional
DATA_PARAMETER_PLACEHOLDER
label : sequence, optional
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think this could be a single string or a sequence?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This might actually need to bestr or list of str

@rcomer
Copy link
Member

The tests failed because of a problem with a new version of pytest which has now been yanked. I’m going to close and re-open to restart the CI.

saranti reacted with thumbs up emoji

@rcomerrcomer closed thisMar 4, 2024
@rcomerrcomer reopened thisMar 4, 2024
@timhoffm
Copy link
Member

timhoffm commentedMar 4, 2024
edited
Loading

AFAICT, this needs a rebase to pick up the pytest pinning.

saranti reacted with thumbs up emoji

@github-actionsgithub-actionsbot added the Documentation: examplesfiles in galleries/examples labelMar 5, 2024
@sarantisaranti marked this pull request as draftMarch 5, 2024 13:17
@saranti
Copy link
ContributorAuthor

@melissawm Thanks for the help yesterday, the rebase seems to have gone fine. The only problem I see now is that all the code having to do with the violin plot shouldn't be there and belongs to#27815

@rcomer
Copy link
Member

@saranti your branch is still 60 commits behindmain. I think you just need

git fetch upstreamgit rebase upstream/main

to get it up to date. That should also get rid of the violinplot changes.

saranti reacted with thumbs up emoji

@github-actionsgithub-actionsbot removed the Documentation: examplesfiles in galleries/examples labelMar 8, 2024
@sarantisaranti marked this pull request as ready for reviewMarch 8, 2024 08:47
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I feel uncomfortable with the scope of the PR - which has prevented me from looking more closely. It mixes the two independent topics legend support and parameter rename. I would I encourage separate PRs or at least separate commits to make it clear which feature is responsible for which code changes, and to ease review.

@sarantisaranti marked this pull request as draftMarch 9, 2024 03:42
@saranti
Copy link
ContributorAuthor

The old tick label test was still there after doinggit pull upstream. I removed it as part of the conflict resolution but it's showing up in the diff 🤔

@rcomer
Copy link
Member

I’ve never usedgit pull upstream so not really sure what that does. To get up to date with changes that have been merged tomain, it is recommended to userebase.
https://matplotlib.org/devdocs/devel/development_workflow.html#rebase-onto-upstream-main

@sarantisarantiforce-pushed thebox_legend_support branch 2 times, most recently from1902592 to9fcf0c0CompareMarch 15, 2024 08:38
Copy link
Member

@timhoffmtimhoffm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

To fix the doc build.

saranti reacted with thumbs up emoji
@timhoffmtimhoffm added this to thev3.9.0 milestoneMar 19, 2024
@timhoffm
Copy link
Member

timhoffm commentedMar 19, 2024
edited
Loading

Milestoning as 3.9 because it would be nice to get this in and IMO it’s ready. Just needs a second review.

Comment on lines 4424 to 4425
raise ValueError("There must be an equal number of legend"
" labels and boxplots.")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This check should probably be in the "input validation" section, and reusedatashape_message.

@QuLogicQuLogic merged commit102d0a6 intomatplotlib:mainMar 21, 2024
@sarantisaranti deleted the box_legend_support branchMarch 23, 2024 05:28
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@QuLogicQuLogicQuLogic left review comments

@timhoffmtimhoffmtimhoffm approved these changes

@rcomerrcomerrcomer left review comments

Assignees
No one assigned
Projects
None yet
Milestone
v3.9.0
Development

Successfully merging this pull request may close these issues.

[ENH]: Legend entries for boxplot
4 participants
@saranti@rcomer@timhoffm@QuLogic

[8]ページ先頭

©2009-2025 Movatter.jp