使用 matplotlib 显示多个 y 轴脊时减小一个子图的宽度

Posted

技术标签:

【中文标题】使用 matplotlib 显示多个 y 轴脊时减小一个子图的宽度【英文标题】:Reduce width of one subplot when showing multiple y- axis spines with matplotlib 【发布时间】:2018-08-22 15:13:18 【问题描述】:

我有一个包含三个子图的图形,排列在一个列中。其中一个图在右侧使用 3 个 y 轴刺。我跟着this tutorial 在子图上插入了多个右轴刺。

我的问题是,通过添加额外的刺,图中的所有子图在 x 方向上都变小了。这改变了所有三个子图的宽度,在其他子图的右侧留下了未使用的空间。

在 y 轴上添加额外的刺时,如何仅调整一个子图的宽度?

下面是一个简化的例子,它产生了与this image中相同的问题

from matplotlib import pyplot as plt

# set up a set of three subplots
fig = plt.figure(figsize=(17, 11))

ax_1_l = fig.add_subplot(3,1,1)
ax_1_r = ax_1_l.twinx()

ax_2_l = fig.add_subplot(3,1,2)
ax_2_r = ax_2_l.twinx()

ax_3_l = fig.add_subplot(3,1,3)
ax_3_r = ax_3_l.twinx()


# add additional axes to the middle subplot as per tutorial
def make_patch_and_spines_invisible(ax):
  ax.set_frame_on(True)
  ax.patch.set_visible(False)
  for sp in ax.spines.values():
    sp.set_visible(False)

ax_2_r_2 = ax_2_l.twinx()
make_patch_and_spines_invisible(ax_2_r_2)
ax_2_r_2.spines['right'].set_position(('axes', 1.05))
ax_2_r_2.spines['right'].set_visible(True)

ax_2_r_3 = ax_2_l.twinx()
make_patch_and_spines_invisible(ax_2_r_3)
ax_2_r_3.spines['right'].set_position(('axes', 1.1))
ax_2_r_3.spines['right'].set_visible(True)

# display the plots
plt.tight_layout()
plt.show()

Sample Output Image from my code

matplotlib 2.1.2 版

【问题讨论】:

嗨,Evan,您能否分享一下工作代码,以便我们重现该图并尝试帮助提供解决方案? 特别是minimal reproducible example 我将尝试将大型程序缩减为显示相同问题的较短脚本。我将不得不用一些样本替换真实数据。 样本数据很好(虽然我不认为这与数据有任何关系,所以也许只创建空子图就足够了..) 按照 DavidG 的建议,我添加了一个没有任何数据的简单代码示例 【参考方案1】:

使用gridspec 解决您的问题的另一种解决方法,您还必须手动设置中间图的右手限制。但是您在这里坚持使用 3 行和 1 列格式,就像您在原始代码中所做的那样。只需将函数定义之前的代码替换为以下几行:

import matplotlib.gridspec as gridspec
gs = gridspec.GridSpec(3, 1)

ax_1_l = plt.subplot(gs[0])
ax_3_l = plt.subplot(gs[2])
ax_1_r = ax_1_l.twinx()
ax_3_r = ax_3_l.twinx()

gs = gridspec.GridSpec(3, 1)
gs.update(right=0.85)  # This is the part where you specify the bound
ax_2_l = plt.subplot(gs[1])
ax_2_r = ax_2_l.twinx()

输出

【讨论】:

谢谢。我接受这个解决方案,因为它非常适合我的代码结构。 David 和 John 还通过他们看到的有限示例代码提供了可行的解决方案。 很高兴它帮助了你!【参考方案2】:

一个可能的答案是使用 matplotlibs subplot2grid 功能。缺点是它不会自动调整大小,你必须手动调整..

将子图的创建替换为:

ax_1_l = plt.subplot2grid((3, 11), (0, 0), colspan=11)
ax_2_l = plt.subplot2grid((3, 11), (1, 0), colspan=10)
ax_3_l = plt.subplot2grid((3, 11), (2, 0), colspan=11)

ax_1_r = ax_1_l.twinx()
ax_2_r = ax_2_l.twinx()
ax_3_r = ax_3_l.twinx()

我制作了一个 3 行 11 列的网格,然后设置 colspan 使子图 2 比其他 2 略小,以便为脊椎留出空间。 (再次尝试和错误的方法,所以不是一个完美的解决方案)

【讨论】:

【参考方案3】:

您可以使用Axes.set_position() 调整各个子图的位置/大小。由于您只想更改上 x 值,您可以执行以下操作:

bb = ax_1_l.get_position()
bb.x1 = 0.97
ax_1_l.set_position(bb)
bb = ax_3_l.get_position()
bb.x1 = 0.97
ax_3_l.set_position(bb)

改变第一个和第三个子图的右边缘。

【讨论】:

以上是关于使用 matplotlib 显示多个 y 轴脊时减小一个子图的宽度的主要内容,如果未能解决你的问题,请参考以下文章

MatPlotLib:同一个散点图上的多个数据集

如何使用Figure(matplotlib FigureCanvasQTAgg)绘制具有多个y轴的共享x轴子图?

Python机器学习入门——科学计算库(Matplotlib)

Python可视化库matplotlib(超详细)

Python使用matplotlib函数subplot可视化多个不同颜色的折线图使用set_major_formatter函数自定义设置y轴数值标签格式为百分比

python_matplotlib作图中有多个Y轴