Skip to content
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

secondary_y plot shows in separate figure #9779

Closed
arski opened this issue Apr 1, 2015 · 11 comments · Fixed by #9812
Closed

secondary_y plot shows in separate figure #9779

arski opened this issue Apr 1, 2015 · 11 comments · Fixed by #9812
Labels
Milestone

Comments

@arski
Copy link

arski commented Apr 1, 2015

Hi, don't know if this is my Python/some module version.. but when I try to do the following, I end up with two figures popping up, instead of the expected one:

df[[0, 1]].plot(kind='bar', stacked=True, ylim=(0, 100))
df[[2]].plot(secondary_y=True, color='orange', linewidth=2.0)

The data in both plots looks right, the left/right y axes are correct etc.. but they're not on the same figure :(

Also if this is of any help, if I do fig = plt.figure() before running the commands above, I end up with another completely empty figure shown to me first..

Sorry if this is something stupid and/or not caused by pandas..

@arski
Copy link
Author

arski commented Apr 1, 2015

Hmm, it works if I do fig, ax = plt.subplots(1, 1) and then add ax=ax to both df.plot() calls above.. Might be worth documenting?

However, there are two bugs now:

  1. the secondary legend is on top of the first one
  2. the plot width is scaled down to the line points, i.e. the first and last bars are cut off by 50%

@arski
Copy link
Author

arski commented Apr 1, 2015

Erm, executing the secondary_y line plot command first and the bar plot second solves issue 2. Now the plot has enough space for the bars.

@jorisvandenbossche
Copy link
Member

Another possibility is doing ax = df[[0,1]].plot(...) and then providing this ax to the second df[[2]].plot(..), or by doing df[2].plot(..) (this is then plotting a series -> added to the existing figure). But, I think your solution of fig, ax = plt.subplots(1, 1) is the cleanest and clearest one.

Providing the ax is documented (see the docstring and http://pandas.pydata.org/pandas-docs/stable/visualization.html), but maybe not explicitly enough (see also #8776). If you have any suggestions on how to improve it, certainly welcome!

For the other questions, can you provide a small reproducible example? (some runnable code with some dummy data that shows the issue)

@arski
Copy link
Author

arski commented Apr 1, 2015

Hmm, the two options you mention work indeed, though somehow I'm now missing the first plot's y axis ticks/labels and the second plot's legend altogether.. Here's the snippet with the shortened version (I was doing df[2] before and it didn't work because my columns had titles, but otherwise that way works indeed, like the doc says!)

from pandas import DataFrame
import matplotlib.pyplot as plt

points = [[50.69922925478467, 23.857641645143786, 2247], [51.11691211658459, 23.30982697233231, 80], [55.37656430470213, 23.25234081849125, 12]]
keys = ['one', 'two', 'three']
df = DataFrame(points, index=keys, columns=['OK', 'OK too', 'Where am I'])

df[[0, 1]].plot(
    kind='bar',
    stacked=True,
    ylim=(0, 100),
)
df['Where am I'].plot(
    color='orange',
    linewidth=2.0,
    mark_right=False,
    secondary_y=True,
)
plt.show()

On the other hand, using the following makes the second plot's legend overlap:

from pandas import DataFrame
import matplotlib.pyplot as plt

points = [[50.69922925478467, 23.857641645143786, 2247], [51.11691211658459, 23.30982697233231, 80], [55.37656430470213, 23.25234081849125, 12]]
keys = ['one', 'two', 'three']
df = DataFrame(points, index=keys, columns=['Cant see this', 'This OK', 'Move me please'])

fig, ax = plt.subplots(1, 1)
fig = df[[0, 1]].plot(
    kind='bar',
    stacked=True,
    ylim=(0, 100),
    ax=ax
)
fig2 = df[[2]].plot(
    color='orange',
    linewidth=2.0,
    mark_right=False,
    ax=ax,
    secondary_y=True,
)
plt.show()

@arski
Copy link
Author

arski commented Apr 1, 2015

PS. This issue has now gone almost completely off-topic.. but still some issues I think :)

@sinhrks
Copy link
Member

sinhrks commented Apr 5, 2015

On first one, you should pass legend=True explicitly because it is disabled for Series by default. Then you will get the same result as latter one (overlapped legend).

The overlapped legend seems to be caused by a bug which is the same as #9610. Expected to be fixed by #9812 as below:

9779

@TomAugspurger
Copy link
Contributor

@arski should be fixed now if you're comfortable running off master. Thanks for the report.

@arski
Copy link
Author

arski commented Apr 5, 2015

Cool, thanks! What about the cut off first/last bars?

@TomAugspurger
Copy link
Contributor

Maybe make a separate issue for that bug, if we don't have one already. You can work around it with the ax.get_xlim() methos.

@jorisvandenbossche jorisvandenbossche added this to the 0.16.1 milestone Apr 6, 2015
@sinhrks
Copy link
Member

sinhrks commented Apr 9, 2015

@arski Because xlim is adjusted by last plot kind, another option is draw fig2 first, then fig. Note that it should affect to legend order.

fig, ax = plt.subplots(1, 1)
fig2 = df[[2]].plot(
    color='orange',
    linewidth=2.0,
    mark_right=False,
    ax=ax,
    secondary_y=True,
)
fig = df[[0, 1]].plot(
    kind='bar',
    stacked=True,
    ylim=(0, 100),
    ax=ax
)

figure_1

@arski
Copy link
Author

arski commented Apr 9, 2015

ah, fair enough I guess, if only the legend order could be adjusted ;)

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 a pull request may close this issue.

5 participants