Matplotlib的tight_layout导致RuntimeError

11 投票
1 回答
3929 浏览
提问于 2025-04-18 00:27

我在使用 plt.tight_layout() 来整理一个包含多个子图的 matplotlib 图表时遇到了问题。

我创建了6个子图作为示例,想用 tight_layout() 来整理它们重叠的文字,但却出现了一个运行时错误。

Traceback (most recent call last):
  File ".\test.py", line 37, in <module>
    fig.tight_layout()
  File "C:\Python34\lib\site-packages\matplotlib\figure.py", line 1606, in tight_layout
    rect=rect)
  File "C:\Python34\lib\site-packages\matplotlib\tight_layout.py", line 334, in get_tight_layout_figure
    raise RuntimeError("")
RuntimeError

我的代码在这里(我使用的是 Python 3.4)。

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 3*np.pi, 1000)

fig = plt.figure()


ax1 = fig.add_subplot(3, 1, 1)

ax2 = fig.add_subplot(3, 2, 3)
ax3 = fig.add_subplot(3, 2, 4)

ax4 = fig.add_subplot(3, 3, 7)
ax5 = fig.add_subplot(3, 3, 8)
ax6 = fig.add_subplot(3, 3, 9)

for ax in [ax1, ax2, ax3, ax4, ax5, ax6]:
    ax.plot(x, np.sin(x))

fig.tight_layout()

plt.show()

我最开始怀疑问题可能是因为子图的大小不一样,不过 tight layout 指南 似乎表明这不应该是个问题。任何帮助或建议都非常感谢。

1 个回答

11

这个错误信息确实不太好理解,不过在if语句中有个小提示可以帮助你找到问题所在。如果你使用IPython,错误追踪信息会提供更多的上下文。下面是我运行你代码时看到的内容:

    332         div_col, mod_col = divmod(max_ncols, cols)
    333         if (mod_row != 0) or (mod_col != 0):
--> 334             raise RuntimeError("")

虽然你可以在不同大小的子图中使用 tight_layout,但它们必须按照规则的网格布局。如果你仔细看看文档,其实是用 plt.subplot2grid 函数来设置图表,这个函数和你想做的事情最相关。

所以,要想得到你想要的效果,你需要在一个3x6的网格上布局:

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 10, 100)
fig = plt.figure()

# Top row
ax1 = plt.subplot2grid((3, 6), (0, 0), colspan=6)

# Middle row
ax2 = plt.subplot2grid((3, 6), (1, 0), colspan=3)
ax3 = plt.subplot2grid((3, 6), (1, 3), colspan=3)

# Bottom row
ax4 = plt.subplot2grid((3, 6), (2, 0), colspan=2)
ax5 = plt.subplot2grid((3, 6), (2, 2), colspan=2)
ax6 = plt.subplot2grid((3, 6), (2, 4), colspan=2)

# Plot a sin wave
for ax in [ax1, ax2, ax3, ax4, ax5, ax6]:
    ax.plot(x, np.sin(x))

# Make the grid nice
fig.tight_layout()

在这里输入图片描述

第一个参数是网格的尺寸,第二个参数是子图在网格中的左上角位置,rowspancolspan 参数则表示每个子图在网格中要占据多少个点。

撰写回答