matplotlib - No xlabel and xticks for twinx axes in subploted figures

扶醉桌前 提交于 2020-01-20 07:58:46

问题


What I want to do is a 2x2 diagrams in a subplot. Then, for each figure, I am going to use two y-axes. Therefore, I used twinx() method for each diagram. The problem as you see in the figure I shared is that it does not show xlabel and xticks for first row. For the second row, everything is fine. I have specified the problem in red font in the figure ("No xlabel and xticks!!!").

Each diagram has its own x-axis and y-axis and there is no sharing in that.

I have tweaked this code a lot and narrowed down the problem maker. It is because I use twinx() in upper rows. If I try to remove the secondary y axis, everything goes back to normal and the xlabel and ylabel for upper rows are shown correctly.

I don't know what is the problem!

This is the code I am working on.

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from io import StringIO

s = StringIO(u"""     amount     price
A     40929   4066443
B     93904   9611272
C    188349  19360005
D    248438  24335536
E    205622  18888604
F    140173  12580900
G     76243   6751731
H     36859   3418329
I     29304   2758928
J     39768   3201269
K     30350   2867059""")

df = pd.read_csv(s, index_col=0, delimiter=' ', skipinitialspace=True)

fig = plt.figure() 

ax_2 = fig.add_subplot(222, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([1, 3, 5, 7, 9])
ax_22.plot([1.0/x for x in [1, 3, 5, 7, 9]])
ax_2.set_xlabel("AX2 X Lablel")
ax_2.set_ylabel("AX2 Y Lablel")
ax_22.set_ylabel("AX2_Twin Y Lablel")


ax_2 = fig.add_subplot(223, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([100, 300, 500, 700, 900])
ax_22.plot([x*x for x in [100, 300, 500, 700, 900]])
ax_2.set_xlabel("AX3 X Lablel")
ax_2.set_ylabel("AX3 Y Lablel")
ax_22.set_ylabel("AX3_Twin Y Lablel")




ax_2 = fig.add_subplot(224, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX4 X Lablel")
ax_2.set_ylabel("AX4 Y Lablel")
ax_22.set_ylabel("AX4_Twin Y Lablel")






ax = fig.add_subplot(221, sharex=None, sharey=None) 
ax2 = ax.twinx() 
width = 0.4
df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1, sharex=False, sharey=False)
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0, sharex=False, sharey=False)

ax.set_xlabel("Alphabets")
ax.set_ylabel('Amount')
ax2.set_ylabel('Price')



plt.subplots_adjust(wspace=0.8, hspace=0.8)
plt.savefig("t1.png", dpi=300)
plt.show()

It generates following figure:

EDITED:

Thanks for the answers. However, my problem still exists when using Pandas in plotting diagrams. I opened a new question. Please take a look at it:

matplotlib - pandas - no xlabel and xticks for twinx axes in subploted figures


回答1:


The code you provided seems to produce the desired result.

That makes me think that there is an issue with your console or matplotlib version - perhaps you can provide more information on how you are running the code.

I would recommend moving the ax.set_xlabel before twinx such as:

ax_2 = fig.add_subplot(222, sharex=None, sharey=None)
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX2 X Lablel")
ax_2.plot([1, 3, 5, 7, 9])

# Becomes...

ax_2 = fig.add_subplot(222, sharex=None, sharey=None)
ax_2.set_xlabel("AX2 X Lablel")
ax_2.plot([1, 3, 5, 7, 9])
ax_22 = ax_2.twinx()

EDIT I would suggest using gridspec instead. See the below working example:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gspec
import numpy as np

fig = plt.figure()
gs = gspec.GridSpec(2, 2)
gs.update(hspace=0.7, wspace=0.7)
ax1 = plt.subplot(gs[0, 0])
ax2 = plt.subplot(gs[1, 0])
ax3 = plt.subplot(gs[0, 1])
ax4 = plt.subplot(gs[1, 1])


x1 = np.linspace(1,10,10)

ax1.plot(x1, x1**2)
ax1.set_xlabel('ax1 x')
ax1_2 = ax1.twinx()
ax1_2.plot(x1, x1**3)
ax1_2.set_ylabel('ax1_2 y')
ax1.set_ylabel('ax1 y')

# To save time I left the other cells blank, but it should work fine.

plt.show()

The above produces this:




回答2:


This is how I approach issues like this one. First try to isolate the issue by reducing your code to a minimum. For instance, this code shows the same problem:

fig = plt.figure()
fig.add_subplot(212)
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)

Now we can see two things:

  1. If I had made a mistake in just 5 lines of code it should be easy to find (at least easier than with the original code). Since I cannot find any mistakes I guess this is a bug in pandas or matplotlib. From the comments it could be a regression introduced in matplotlib 1.5.1.

  2. There are two unusual things in this code:

    • The lower plot is created before the upper plot.
    • The dataframe is plotted in the primary axes after the twin axes is created.

Unusual things are more likely to trigger hidden bugs in the underlying libraries, so better avoid them if possible. Now let's see what happens if we create the subplots in the usual top-down order:

fig = plt.figure() 
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)
fig.add_subplot(212)

It seems to work, so let's try the same with the original code:

fig = plt.figure() 

ax = fig.add_subplot(221, sharex=None, sharey=None) 
ax2 = ax.twinx() 
width = 0.4
df.amount.plot(kind='bar', color='red', ax=ax, width=width, position=1, sharex=False, sharey=False)
df.price.plot(kind='bar', color='blue', ax=ax2, width=width, position=0, sharex=False, sharey=False)

ax_2 = fig.add_subplot(222, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([1, 3, 5, 7, 9])
ax_22.plot([1.0/x for x in [1, 3, 5, 7, 9]])
ax_2.set_xlabel("AX2 X Lablel")
ax_2.set_ylabel("AX2 Y Lablel")
ax_22.set_ylabel("AX2_Twin Y Lablel")

ax_2 = fig.add_subplot(223, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.plot([100, 300, 500, 700, 900])
ax_22.plot([x*x for x in [100, 300, 500, 700, 900]])
ax_2.set_xlabel("AX3 X Lablel")
ax_2.set_ylabel("AX3 Y Lablel")
ax_22.set_ylabel("AX3_Twin Y Lablel")

ax_2 = fig.add_subplot(224, sharex=None, sharey=None) 
ax_22 = ax_2.twinx()
ax_2.set_xlabel("AX4 X Lablel")
ax_2.set_ylabel("AX4 Y Lablel")
ax_22.set_ylabel("AX4_Twin Y Lablel")

ax.set_xlabel("Alphabets")
ax.set_ylabel('Amount')
ax2.set_ylabel('Price')

plt.subplots_adjust(wspace=0.8, hspace=0.8)
plt.savefig("t1.png", dpi=300)
plt.show()

So problem solved (at least for me) via a workaround. An actual fix would be better but perfect is the enemy of good and now the subplots are created in a more logical order, which improves readability.



来源:https://stackoverflow.com/questions/35211142/matplotlib-no-xlabel-and-xticks-for-twinx-axes-in-subploted-figures

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!