matplotlib - 子图中的 twinx 轴没有 xlabel 和 xticks
Posted
技术标签:
【中文标题】matplotlib - 子图中的 twinx 轴没有 xlabel 和 xticks【英文标题】:matplotlib - No xlabel and xticks for twinx axes in subploted figures 【发布时间】:2016-05-14 15:53:52 【问题描述】:我想要做的是子图中的 2x2 图表。然后,对于每个图形,我将使用两个 y 轴。因此,我对每个图表都使用了 twinx() 方法。您在我分享的图中看到的问题是它没有显示第一行的 xlabel 和 xticks。对于第二排,一切都很好。我已经在图中用红色字体指定了问题(“No xlabel and 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()
生成如下图:
已编辑:
感谢您的回答。但是,在绘图中使用 Pandas 时我的问题仍然存在。我开了一个新问题。请看一下:
matplotlib - pandas - no xlabel and xticks for twinx axes in subploted figures
【问题讨论】:
【参考方案1】:这就是我处理此类问题的方式。首先尝试通过将代码减少到最低限度来隔离问题。例如,这段代码显示了同样的问题:
fig = plt.figure()
fig.add_subplot(212)
ax = fig.add_subplot(211)
ax2 = ax.twinx()
pd.Series(range(10)).plot(ax=ax)
现在我们可以看到两件事:
如果我在 5 行代码中犯了错误,应该很容易找到(至少比使用原始代码更容易)。由于我找不到任何错误,我猜这是 pandas 或 matplotlib 中的错误。从 cmets 来看,它可能是 matplotlib 1.5.1 中引入的回归。
这段代码中有两个不寻常的地方:
下图在上图之前创建。 创建双坐标轴后,数据框将绘制在主轴上。不寻常的事情更有可能触发底层库中的隐藏错误,因此最好尽可能避免它们。现在让我们看看如果我们按照通常的自上而下的顺序创建子图会发生什么:
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)所做的升级。我还应该提到,我将生成上图的代码向下移动的原因是它不起作用,我认为这种向下移动的更改可能会帮助解决这个问题。但是,我非常感谢您的时间和精力(我也接受了您的回答)。 如果定义“ax3 = fig.add_subplot(212)”并调用“pd.Series(range(10)).plot(ax=ax3)”,ax 的 x 轴仍然消失( ?)。 @Pat 我不知道您想在哪里添加该代码,但我鼓励您自己尝试。【参考方案2】:您提供的代码似乎产生了预期的结果。
这让我认为您的控制台或 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()
上面产生了这个:
【讨论】:
谢谢 Oniow。即使有你提到的变化,数字也没有变化!我正在使用 Ubuntu 14.04 64 位的 Mac 上运行我的脚本。 Python:2.7.11(使用 GCC 4.4.7 编译) Matplotlib:1.5.1 而且,我使用 Anaconda 2.4.0 作为我的 Python 包的包管理器。 您是否以任何方式更改了我的代码?我问这个是因为我需要生成图表并且我想知道我是否犯了错误。我提到的上述任何系统配置是否与您的不同?感谢您的宝贵时间。 你好 Millad - 我能够使用 Python 3.4 和 Matplotlib 1.5.0 以及使用 Anaconda 生成该图。我没有对您的代码进行任何更改以获得所需的结果。它可能是 python 3 vs. 2 的事情——但我对此表示怀疑。你用的是什么接口?您是直接保存图形还是将其输出到 Ipython 控制台之类的东西? 无论如何,我建议改用gridspec。当我遇到类似的问题时,我的运气要好得多。查看我编辑的回复。 谢谢@Oniow。 :) 对此,我真的非常感激。gridspec
似乎在我的 Python 2.7 上完美运行,我认为这是问题的根源,因为您提到您使用的是 Python 3。我正在使用 Python rawly,所以没有 IPython,没有其他花哨东西 :)。而且,我在我保存的文件和plt.show()
的输出窗口上也看到了这种行为。我使用了您的代码,它在我的机器上适用于所有 4 个图表和我想要的所有轴:)。我接受了您的答案作为解决方案,但由于从 *** 的角度来看,我没有经验 足够,因此它可能不会显示为答案。以上是关于matplotlib - 子图中的 twinx 轴没有 xlabel 和 xticks的主要内容,如果未能解决你的问题,请参考以下文章
使用 Seaborn 和 Matplotlib 在热图和线图的共享子图中对齐 x 轴刻度