Matplotlib - 在子图中创建twinx坐标轴时,无法显示xlabel和xticks。

10
我想做的是在一个子图中画一个2x2的图表。然后,对于每个图表,我将使用两个y轴。因此,我为每个图表使用了twinx()方法。正如您在共享的图中看到的那样,问题在于它不显示第一行的xlabel和xticks。对于第二行,一切都很好。我在图中用红色字体指出了问题(“没有xlabel和xticks!!!”)。
每个图形都有自己的x轴和y轴,并且没有共享。
我已经调整了这个代码并缩小了问题的范围。这是因为我在上面的行中使用了twinx()。如果我尝试删除辅助y轴,一切就会恢复正常,上面行的xlabel和ylabel将正确显示。
我不知道问题在哪里!
这是我正在工作的代码。
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()

它生成以下图形:

通过Python代码得到的输出图形

编辑:

感谢您的回答。然而,当使用Pandas绘制图表时,我的问题仍然存在。我发布了一个新的问题,请查看:

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

2个回答

6
您提供的代码似乎产生了预期的结果。

test run

这让我想到你的控制台或matplotlib版本存在问题——也许你可以提供更多关于如何运行代码的信息。
我建议将ax.set_xlabel移动到twinx之前,例如:
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()

编辑 我建议使用gridspec。请参见下面的工作示例:

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()

以上代码会产生以下结果:

gridspec example


1
谢谢Oniow。即使按照你提到的更改,图形也没有变化! 我正在我的Mac上运行Ubuntu 14.04 64位的脚本。 Python版本:2.7.11(使用GCC 4.4.7编译) Matplotlib版本:1.5.1此外,我使用Anaconda 2.4.0作为Python包的软件包管理器。 - mgNobody
你有更改我的代码吗?我问这个是因为我需要生成图表,我想知道是否我犯了错误。我提到的以上系统配置中有哪些与你的不同吗?感谢你的时间。 - mgNobody
你好Millad - 我能够使用Python 3.4和Matplotlib 1.5.0以及Anaconda生成那个图。我没有更改您的代码就得到了所需的结果。这可能是Python 3与2之间的问题,但我不确定。您使用的是什么接口?您是直接保存图形还是将其输出到类似于Ipython控制台的东西? - Oniow
无论如何,我建议使用gridspec。当我遇到类似的问题时,我用它表现得更好。请查看我的编辑后答复。 - Oniow
1
感谢 @Oniow。 :) 我非常感激。gridspec 在我的 Python 2.7 上似乎完美运行,我认为这可能是问题的根源,因为你提到你正在使用 Python 3。我在使用纯 Python,没有 IPython,也没有其他花哨的东西 :)。并且,我在保存的文件和 plt.show() 的输出窗口中都看到了这种行为。我在我的机器上使用了你的代码,并且对于我想要的所有 4 个图表和所有轴,它都起作用了 :)。我接受了你的答案作为解决方案,但由于我从 stackoverflow 的角度来看经验不足,它可能不会显示为答案。 - mgNobody

5
这是我解决这类问题的方法。首先,尝试通过将代码减少到最少来隔离问题。例如,此代码显示相同的问题:
fig = plt.figure()
fig.add_subplot(212)
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)

错误的图形

现在我们能够看到以下两件事情:

  1. 如果我只是在五行代码中犯了一个错误,那么应该很容易找到(至少比原始代码更容易)。由于我找不到任何错误,我猜测这是pandas或matplotlib中的一个bug。从评论中可以看出,这可能是在matplotlib 1.5.1中引入的一个回归。

  2. 此代码中有两个不寻常的地方:

    • 下部图形在上部图形之前创建。
    • 数据框绘制在双轴创建之后的主轴上。

不寻常的事情更容易触发底层库中的隐藏错误,因此最好避免它们。现在让我们看看如果按照常规的自上而下顺序创建子图会发生什么:

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

正确的图表

看起来这个图表正常工作,那么让我们尝试使用原始代码:

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()

问题已解决

所以,通过一个变通办法,我的问题已得到解决。虽然完美的修复方案更好,但是现在子图按更加合理的顺序创建,这提高了可读性。


天啊,我很困惑!之前它不起作用,但现在它运行得很好!我认为这可能是由于我对Python包(matplotlib和pandas)进行的升级所致。我还应该提到,我将生成我的上部图的代码下移的原因是它不起作用,我认为也许这是某种错误,这个下移的更改会有所帮助。无论如何,非常感谢您的时间和努力(我也接受了您的答案)。 - mgNobody
{btsdaf} - Pat
@Pat,我不知道你想在哪里添加那段代码,但我鼓励你自己尝试。 - Stop harming Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接