Fix missing tick labels on twinned axes.
State: closed

## 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 internally sharing an axis, they are twinned. If their positions are different, they are externally sharing the common axis.

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 **does not**, ignore
axes which are only twinned. 

Which means that twinned-only axes wrongly lose their tick labels.

## The cure:

This commit introduces `_ignore_colocated_axes()` which ignores any
axes in a list which have the same position as the given axis. It uses
this function to envelope calls from `_handle_shared_axes()` to
`Axes.get_shared_{x,y}_axes().get_siblings(ax)`.

## The demonstration test case:

Note especially the axis labels (and associated tick labels).

```python
#!/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])
plots[0][2] = plt.subplot(233, sharex=plots[1][2])

# Create *internally* shared axes
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()
```
---

- [ ] closes #27812
- [ ] tests added / passed
- [ ] passes `black pandas`
- [ ] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [ ] whatsnew entry


Labels:
name: Visualization
description: plotting

Comments:
Hello @ebardie! Thanks for updating this PR. We checked the lines you've touched for [PEP 8](https://www.python.org/dev/peps/pep-0008) issues, and found:





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

##### Comment last updated at 2019-12-10 11:34:09 UTC
@ebardie : Thanks for opening this PR and welcome to `pandas` !

FYI: as a matter of procedure, we generally open issues first before creating the PR to address, just so that we can better assess how to address it in the first place.  No need to close this PR, but just so you know for subsequent contributions.
> @ebardie : Thanks for opening this PR and welcome to `pandas` !
> 
> FYI: as a matter of procedure, we generally open issues first before creating the PR to address, just so that we can better assess how to address it in the first place. No need to close this PR, but just so you know for subsequent contributions.

Thanks. Will do.

Can you add a test?
Closing as I think this is stale, but @ebardie certainly ping if you'd like to pick back up and can address comments around test
Whoops sorry I see test was added; reopening
@WillAyd I presume there's nothing more I need to do other than wait 'til this bubbles to the top of @TomAugspurger's (presumably rather extensive) ToDo list?
I'm not sure about the additional complexity here. If you're using matplotlib to create the axes in the first place, can you not pass your Series / DataFrame to whatever `Axes.plot` your using?
can you merge master and will look again
@ebardie can you merge master?
Closing as I think stale but ping if you'd like to continue and can merge master
> Closing as I think stale but ping if you'd like to continue and can merge master

@WillAyd I've finally had some time for this! I've rebased on current master. Can you re-open or should I issue a fresh PR?


pls open a fresh PR