【问题标题】:Is it possible to reduce the width of a single subplot in gridspec/Matplotlib?是否可以减少 gridspec/Matplotlib 中单个子图的宽度?
【发布时间】:2021-10-17 04:13:45
【问题描述】:

我有一个使用 gridspec 创建的子图网格。我知道如何在 gridspec 中创建跨行和列的子图。是否可以少量减少单个子图的宽度?例如,我们可以为单个子图设置宽度比吗?我想要的方式在图像中用红色标记。

我的代码如下所示:

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

plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(3, 5,  height_ratios=[0.5,1,1])

for i in range(1, 3):
    for j in range(5):
      ax = plt.subplot(gs[i, j])

ax1 = plt.subplot(gs[0,1:2])
ax2 = plt.subplot(gs[0,2:])

for ax in [ax1, ax2]:
    ax.tick_params(size=0)
    ax.set_xticklabels([])
    ax.set_yticklabels([])

我尝试了什么:

我尝试将宽度比设置为width_ratios = [1,1,1,1,0.5],但这会减小整列(最后一列)的宽度。

【问题讨论】:

  • 您可以随时在要缩小的子图上执行 ax.set_postion。

标签: python matplotlib width subplot


【解决方案1】:

您可以使用GridSpec for multicolumn layouts。这里创建一个 3 行 7 列的网格,宽度比为 [1,1,0.5,0.5,1,0.5,0.5],并在组合的 0.5 列中的第二行和第三行中绘制轴。

gs = GridSpec(3, 7, figure=fig, width_ratios=[1,1,0.5,0.5,1,0.5,0.5])
ax_merged_top = fig.add_subplot(gs[0, 3:6])
ax_row1_pseudocol3 = fig.add_subplot(gs[1, 2:4])

这是一个完整的例子:

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

plt.figure(figsize=(6, 4))
gs = gridspec.GridSpec(3, 7, figure=fig,
                       height_ratios=[0.5,1,1],
                       width_ratios=[1,1,0.5,0.5,1,0.5,0.5])

ax1 = plt.subplot(gs[0,1])
ax_merged_top = plt.subplot(gs[0, 3:6])

for row in [1,2]:
    extra=0
    for col in range(5):
        if col in (2,4):
            ax = plt.subplot(gs[row,col+extra:col+extra+2])
            extra+=1
        else:
            ax = plt.subplot(gs[row,col+extra])

现在您可以将 width_ratio 更改为任何值,前提是最初设置为 [0.5,0.5] 的数字加起来为 1,例如下面的 width_ratios=[1,1,0.3,0.7,1,0.5,0.5]

【讨论】:

  • 这也会改变其他子图的列宽。
【解决方案2】:

感谢@JodyKlymak 提及ax.set_postion 方法。 @mozway 提供了一个可行的解决方案,但在我的代码中添加这几行给了我想要的输出:

bb = ax2.get_position()
bb.x1 = 0.84
ax2.set_position(bb)

bb = ax2.get_position()
bb.x0 = 0.50
ax2.set_position(bb)

【讨论】:

  • 类似的做法ll, bb, ww, hh = ax2017.get_position().boundsax2017.set_position([ll, bb, ww*0.8, hh*0.8])