如何使用Matplotlib中的subplot2grid/gridspec获取现有的子图轴?

5
我在使用Matplotlib绘图库时遇到了一个问题,就是当我直接使用gridspec或subplot2grid指定绘图位置时,我无法访问现有的子图。如果使用常规的subplot规范,例如add_subplot(211),则会返回任何现有的轴。但是,使用gridspec/subplot2grid似乎会破坏任何现有的轴。我该如何使用gridspec/subplot2grid检索现有的轴对象?这是预期的行为还是我漏掉了什么?我希望找到一种解决方案,不必为轴对象定义占位符。

示例:

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

x = np.linspace(0,10,100)
y1 = np.cos(x)
y2 = np.sin(x)

fig = plt.figure()
ax = fig.add_subplot(211)
ax.plot(x,y1, '-b')
ax = fig.add_subplot(212)
ax.plot(x,y2, '-b')
ax = fig.add_subplot(211) #here, the existing axes object is retrieved
ax.plot(x,y2, '-r')

fig = plt.figure()
gs = gridspec.GridSpec(2,1)
ax = fig.add_subplot(gs[0,0])
ax.plot(x,y1, '-b')
ax = fig.add_subplot(gs[1,0])
ax.plot(x,y2, '-b')
# using gridspec (or subplot2grid), existing axes
# object is apparently deleted
ax = fig.add_subplot(gs[0,0])
ax.plot(x,y2, '-r')

plt.show()

最简单的方法就是自己保留对它们的引用。 - tacaswell
是的,很容易做到,我想到目前为止我必须坚持这个解决方案。然而,我认为仍然需要一个统一的行为来处理 add_plot 等函数对不同子图格式的指定方式。 - bach
最好的表达观点的地方是在 Github 上的问题(issue)中 ;) - tacaswell
1个回答

4
这实际上是一个关于add_subplot如何确定是否存在一个axes的微妙bug。问题归结为以下事实:
In [220]: gs[0, 0] == gs[0, 0]
Out[220]: False

由于每次调用 gridspec.__getitem__ 都会返回一个新对象,而 SubplotSpec 没有重载 __eq__,所以python在寻找现有ax时检查“这是同一个内存中的对象吗”。这就是问题所在。
然而,我的天真尝试通过向 SubplotSpec 添加 __eq__ 并对 matplotlib.gridspec.SubplotSpec 进行猴子补丁来修复它失败了(我没有时间弄清楚原因),但如果您添加...
def __eq__(self, other):
    return all((self._gridspec == other._gridspec,
                self.num1 == other.num1,
                self.num2 == other.num2))

要解决这个问题,可以打开位于matplotlib/gridspec.pyclass SubplotSpec(object) ,转到第380行,然后重新从源代码安装即可。

此外,还可以尝试修复这个问题的PR,但可能会导致其他问题。


感谢您的澄清和纠正问题所付出的努力。 - bach

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