Skip to content

BUG: Fix missing tick labels on twinned axes #33767

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

Conversation

ebardie
Copy link
Contributor

@ebardie ebardie commented Apr 24, 2020

Background:

Multi-row and/or multi-column subplots can utilize shared axes.

An external share happens at axis creation when a sharex or sharey
parameter is specified.

An internal share, or twinning, occurs when an overlayed axis is created
by the Axes.twinx() or Axes.twiny() calls.

The two types of sharing can be distinguished after the fact in the
following manner. If two axes sharing an axis also have the same
position, they are not in an external axis share, they are twinned.

For externally shared axes Pandas automatically removes tick labels for
all but the last row and/or first column in
./pandas/plotting/_matplotlib/tools.py's function _handle_shared_axes().

The problem:

_handle_shared_axes() should be interested in externally shared axes,
whether or not they are also twinned. It should, but doesn't, ignore
axes which are only twinned. Which means that twinned-only axes wrongly
lose their tick labels.

The cure:

This commit introduces has_externally_shared_axis() which identifies
externally shared axes and uses it to expand upon the existing use of
len(Axes.get_shared
{x,y}_axes().get_siblings(a{x,y})) in
_handle_shared_axes() which miss these cases.

The demonstration test case:

Note especially the axis labels (and associated tick labels).

#!/usr/bin/python3

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Create data
df = pd.DataFrame({'a': np.random.randn(1000),
                   'b': np.random.randn(1000)})

# Create figure
fig = plt.figure()
plots = fig.subplots(2, 3)

# Create *externally* shared axes
plots[0][0] = plt.subplot(231, sharex=plots[1][0])
# note: no plots[0][1] that's the twin only case
plots[0][2] = plt.subplot(233, sharex=plots[1][2])

# Create *internally* shared axes
# note: no plots[0][0] that's the external only case
twin_ax1 = plots[0][1].twinx()
twin_ax2 = plots[0][2].twinx()

# Plot data to primary axes
df['a'].plot(ax=plots[0][0], title="External share only").set_xlabel("this label should never be visible")
df['a'].plot(ax=plots[1][0])

df['a'].plot(ax=plots[0][1], title="Internal share (twin) only").set_xlabel("this label should always be visible")
df['a'].plot(ax=plots[1][1])

df['a'].plot(ax=plots[0][2], title="Both").set_xlabel("this label should never be visible")
df['a'].plot(ax=plots[1][2])

# Plot data to twinned axes
df['b'].plot(ax=twin_ax1, color='green')
df['b'].plot(ax=twin_ax2, color='yellow')

# Do it
plt.show()

See images produced by this code for problem and fixed cases at the bug report: #33819.

@alimcmaster1 alimcmaster1 added the Visualization plotting label Apr 26, 2020
@alimcmaster1
Copy link
Member

Thanks for the PR and detailed explanation. Can we open an issue - and ref it in the test?

@ebardie
Copy link
Contributor Author

ebardie commented Apr 27, 2020

Thanks for the PR and detailed explanation. Can we open an issue - and ref it in the test?

I've opened #33819 which has screenshot images produced by running the example code with the problem and after the proposed fix has been applied.

Copy link
Member

@MarcoGorelli MarcoGorelli left a comment

Choose a reason for hiding this comment

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

Thanks @ebardie !

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch 3 times, most recently from 4167f13 to eef11a5 Compare June 1, 2020 12:27
Copy link
Member

@charlesdong1991 charlesdong1991 left a comment

Choose a reason for hiding this comment

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

Hey, @ebardie thanks for the PR, looks nice!

The part i think needs to improve is the testing. It is fine to test the internal function itself, but generally we want to test how users will see the difference from plotting api perspective. e.g. df.plot(blabla) and then assert the axis labels change etc. Quite similar to what you have in your example in the issue.

Therefore, I would prefer to replace this internal function test with the example you have in the issue and test if axis label is changed etc.

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

ping after you can address @charlesdong1991 comments

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from eef11a5 to c96e671 Compare June 22, 2020 20:37
@pep8speaks
Copy link

pep8speaks commented Jun 22, 2020

Hello @ebardie! Thanks for updating this PR. We checked the lines you've touched for PEP 8 issues, and found:

There are currently no PEP 8 issues detected in this Pull Request. Cheers! 🍻

Comment last updated at 2020-09-23 05:25:01 UTC

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from c96e671 to 4c00f01 Compare June 22, 2020 21:14
@ebardie
Copy link
Contributor Author

ebardie commented Jun 22, 2020

ping after you can address @charlesdong1991 comments

Hi @jreback . I've made changes that suit @charlesdong1991. Pinging as requested.

@charlesdong1991
Copy link
Member

charlesdong1991 commented Jun 23, 2020

nice! @ebardie not big deal at all: generally would be nicer to add issue number in tests so that they can easily be tracked in the future, but i think fine this way. could be a tip for your future PRs

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from 4c00f01 to e1cd544 Compare June 23, 2020 13:04
@ebardie
Copy link
Contributor Author

ebardie commented Jun 23, 2020

nice! @ebardie not big deal at all: generally would be nicer to add issue number in tests so that they can easily be tracked in the future, but i think fine this way. could be a tip for your future PRs

Easily remedied now, so I've done so.

Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

test comment & pls add a note in plotting bug fixes for 1.1

@jreback jreback requested a review from TomAugspurger June 24, 2020 15:03
@ebardie ebardie requested a review from jreback June 24, 2020 17:40
@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from e1cd544 to 701fd3f Compare June 24, 2020 17:57
Copy link
Contributor

@jreback jreback left a comment

Choose a reason for hiding this comment

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

this looked ok
can u merge master and ping on green
cc @WillAyd @TomAugspurger

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch 3 times, most recently from 1822447 to 3fc8bee Compare July 21, 2020 19:55
@MarcoGorelli
Copy link
Member

I just tried merging master, as this looked ready, although pandas/tests/plotting/test_misc.py::TestDataFramePlots::test_has_externally_shared_axis is failing during CI (even though it passes when I run it locally)

@MarcoGorelli MarcoGorelli added this to the 1.2 milestone Sep 19, 2020
@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch 2 times, most recently from 0dea8eb to f1e6f03 Compare September 21, 2020 15:07
@ebardie
Copy link
Contributor Author

ebardie commented Sep 21, 2020

@charlesdong1991 @MarcoGorelli : I have re-made changes against current master and your suggestions above. Built locally, and tested with the demonstration test case above, and against my specific use case (https://gitlab.com/eBardie/topplot). pytest pandas/tests/plotting/test_misc.py -v -k externally is happy. CI is happy.

@MarcoGorelli
Copy link
Member

Thanks for updating and for your patience! @charlesdong1991 good to go?

@charlesdong1991 charlesdong1991 changed the title Fix missing tick labels on twinned axes. BUG: Fix missing tick labels on twinned axes Sep 22, 2020
Copy link
Member

@charlesdong1991 charlesdong1991 left a comment

Choose a reason for hiding this comment

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

@MarcoGorelli I think it's good to go, but I requested the review from @jreback or @WillAyd for a further look

Copy link
Member

@charlesdong1991 charlesdong1991 left a comment

Choose a reason for hiding this comment

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

@ebardie I am very sorry to block your PR again, just a minor comment when I came across your whatsnew

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch 2 times, most recently from d3d840c to 2de2ec9 Compare September 22, 2020 10:05
@ebardie

This comment has been minimized.

@@ -331,6 +331,7 @@ Plotting

- Bug in :meth:`DataFrame.plot` was rotating xticklabels when ``subplots=True``, even if the x-axis wasn't an irregular time series (:issue:`29460`)
- Bug in :meth:`DataFrame.plot` where a marker letter in the ``style`` keyword sometimes causes a ``ValueError`` (:issue:`21003`)
- Twinned axes were losing their tick labels which should only happen to all but the last row or column of 'externally' shared axes (:issue:`33819`)
Copy link
Member

Choose a reason for hiding this comment

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

Is "externally" shared axes a standard term?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, hence the quotes. MPL overloading the term "axes" is problem:

Twinned axes were losing their tick labels which should only happen to all but the last row or column of axes shared between axes (:issue:33819)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I should add that this is explained more thoroughly in the linked Issue #33819

@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from 2de2ec9 to 62a98a2 Compare September 22, 2020 23:37
@ebardie ebardie force-pushed the ebardie/fix_twinx_sharex_tickx_label_confusion branch from 62a98a2 to dcb133b Compare September 23, 2020 05:24
@ebardie
Copy link
Contributor Author

ebardie commented Sep 23, 2020

@WillAyd Okay, changes made as per your requests. Tested and builds on the CI.

Copy link
Member

@WillAyd WillAyd left a comment

Choose a reason for hiding this comment

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

lgtm

@WillAyd
Copy link
Member

WillAyd commented Sep 29, 2020

@TomAugspurger @jreback for any remaining comments

@jreback jreback merged commit 235e5b7 into pandas-dev:master Sep 30, 2020
@jreback
Copy link
Contributor

jreback commented Sep 30, 2020

thanks @ebardie and thanks for the patience, we have lots of PRs!

@ebardie
Copy link
Contributor Author

ebardie commented Sep 30, 2020

thanks @ebardie and thanks for the patience, we have lots of PRs!

\o/ and thanks.

I espeically appreciate your appreciation of the understandable-but-frustrating delays :)

My thanks to you all for keeping Pandas going and growing!

kesmit13 pushed a commit to kesmit13/pandas that referenced this pull request Nov 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: Missing tick labels on twinned axes
7 participants