Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Boxplot: Median line is now bound within the box for all linewidths #23335

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/matplotlib/axes/_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3991,7 +3991,13 @@ def bxp(self, bxpstats, positions=None, widths=None, vert=True,
if zorder is None:
zorder = mlines.Line2D.zorder

zdelta = 0.1
# Use 'butt' as the default capstyle to avoid a visual overlap of
# the median line and the boxplot
if medianprops.get('solid_capstyle') is None:
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
if medianprops.get('solid_capstyle') is None:
if medianprops is None or medianprops.get('solid_capstyle', None) is None:

This is causing the test failure. Also, providing a default option for get avoid an error in case the element is not there.

medianprops['solid_capstyle'] = 'butt'

# put the mean and median line below the box for visual improvement
zdelta = -0.1
Copy link
Member

Choose a reason for hiding this comment

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

Won't this lead to that the lines disappear if the box is colored?

Copy link
Author

Choose a reason for hiding this comment

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

You are right. The lines disappear due to the change of the zdelta. I am not sure what the intended result should be. As you described (#19409 (comment)), the mean and median lines have a different cap style. How should the desired result look?

Copy link
Member

Choose a reason for hiding this comment

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

My comment there did clearly not take filled boxes into account...

I think that is really the main problem here: what should it look like? I've googled a bit and there seems to be no real consensus if the lines should extend in a certain way.

Anyway, I guess that there are two options here:

  1. simply change the caps as you currently do and do not change the zorder.
  2. use something like clip_on=True, clip_path=box to the line (where box is the actual box object). If that is the right one is hard to say though. This should at least work for the median line. (The mean line may disappear if it is not in the box though.) However, I think that this will give exactly the same result as it is clipped using the "theoretical zero width line" rather than the actual line.

So probably just reverting the zorder change is enough.

If you can provide an image of the results (e..g using any of the examples in #19409, possibly with exaggerated line widths), that would simplify the review. (Just paste it in a comment.)

Copy link
Member

Choose a reason for hiding this comment

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

I would actually strongly consider an image test here so we can codify what this should look like.

Copy link
Author

Choose a reason for hiding this comment

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

Thank you for the detailed answer. I will go with option 1 then.
Also I will read further into the image tests and provide a test for it.


def merge_kw_rc(subkey, explicit, zdelta=0, usemarker=True):
d = {k.split('.')[-1]: v for k, v in rcParams.items()
Expand Down
9 changes: 9 additions & 0 deletions lib/matplotlib/tests/test_axes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,15 @@ def test_boxplot_zorder():
assert ax.boxplot(x, zorder=10)['boxes'][0].get_zorder() == 10


@check_figures_equal()
def test_boxplot_median_bound_by_box(fig_test, fig_ref):
data = np.arange(3)
medianprops_test = {"linewidth": 12}
medianprops_ref = {**medianprops_test, "solid_capstyle": "butt"}
fig_test.subplots().boxplot(data, medianprops=medianprops_test)
fig_ref.subplots().boxplot(data, medianprops=medianprops_ref)


def test_boxplot_marker_behavior():
plt.rcParams['lines.marker'] = 's'
plt.rcParams['boxplot.flierprops.marker'] = 'o'
Expand Down