matplotlib:我可以创建AxesSubplot对象,然后将它们添加到Figure实例中吗?


76

综观matplotlib文档,似乎标准的方式来添加AxesSubplot一个Figure是使用Figure.add_subplot

from matplotlib import pyplot

fig = pyplot.figure()
ax = fig.add_subplot(1,1,1)
ax.hist( some params .... )

我希望能够AxesSubPlot独立于图形创建类似对象,因此可以在不同图形中使用它们。就像是

fig = pyplot.figure()
histoA = some_axes_subplot_maker.hist( some params ..... )
histoA = some_axes_subplot_maker.hist( some other params ..... )
# make one figure with both plots
fig.add_subaxes(histo1, 211)
fig.add_subaxes(histo1, 212)
fig2 = pyplot.figure()
# make a figure with the first plot only
fig2.add_subaxes(histo1, 111)

这有可能matplotlib吗?如果可以,我该怎么做?

更新:我尚未设法使轴和图形的创建脱钩,但是下面的答案中的以下示例可以轻松地在新的或olf图形实例中重用先前创建的轴。这可以用一个简单的函数来说明:

def plot_axes(ax, fig=None, geometry=(1,1,1)):
    if fig is None:
        fig = plt.figure()
    if ax.get_geometry() != geometry :
        ax.change_geometry(*geometry)
    ax = fig.axes.append(ax)
    return fig

您的函数plot_axes似乎不再起作用。
吉姆

Answers:


35

通常,您只需将轴实例传递给函数。

例如:

import matplotlib.pyplot as plt
import numpy as np

def main():
    x = np.linspace(0, 6 * np.pi, 100)

    fig1, (ax1, ax2) = plt.subplots(nrows=2)
    plot(x, np.sin(x), ax1)
    plot(x, np.random.random(100), ax2)

    fig2 = plt.figure()
    plot(x, np.cos(x))

    plt.show()

def plot(x, y, ax=None):
    if ax is None:
        ax = plt.gca()
    line, = ax.plot(x, y, 'go')
    ax.set_ylabel('Yabba dabba do!')
    return line

if __name__ == '__main__':
    main()

要回答您的问题,您始终可以执行以下操作:

def subplot(data, fig=None, index=111):
    if fig is None:
        fig = plt.figure()
    ax = fig.add_subplot(index)
    ax.plot(data)

另外,您可以简单地将轴实例添加到另一个图形中:

import matplotlib.pyplot as plt

fig1, ax = plt.subplots()
ax.plot(range(10))

fig2 = plt.figure()
fig2.axes.append(ax)

plt.show()

调整其大小以匹配其他子图“形状”也是可能的,但是它将很快变得麻烦不已。以我的经验,对于复杂的情况,仅绕过图形或轴实例(或实例列表)的方法要简单得多。


+1这很有用,但在我看来,轴仍与图形和/或pyplot中的某些状态耦合。按照您的示例,我无法真正将轴创建与图形制作和绘图分离。
juanchopanza

轴从根本上链接到matplotlib中的特定图形。这是不可能的。但是,您仍然可以通过仅传递轴和图形对象来完全“将轴创建与图形制作和绘图分离”。我不太确定我会遵循您的意愿...
Joe Kington

好吧,实际上,我猜他们并没有像我想的那样紧密地联系在一起。您可以将相同的轴添加到不同的图形。(只需这样做fig2.axes.append(ax1))就可以调整其大小以匹配不同的子图形状。不过,这可能会带来更多的麻烦,而不是值得的……
Joe Kington

4
在Enthought 7.3-2(matplotlib 1.1.0)中,将轴实例添加到另一个图形(最后一个示例)对我不起作用。
aaren 2012年

13
@aaren-它不起作用,因为在较新版本的matplotlib中已更改了图形的轴堆栈的工作方式。现在不应该故意在不同的图形之间共享轴。作为一种解决方法,您可以执行此操作fig2._axstack.add(fig2._make_key(a), a),但是它有些hacking,并且将来可能会更改。它似乎工作正常,但可能会破坏某些东西。
乔·肯顿

19

下面显示了如何将轴从一个图形“移动”到另一个图形。这是@JoeKington的最后一个示例的预期功能,该示例在较新的matplotlib版本中不再起作用,因为轴不能一次存在于多个图形中。

首先,您需要从第一个图形中删除轴,然后将其附加到下一个图形中,并为其留一些位置。

import matplotlib.pyplot as plt

fig1, ax = plt.subplots()
ax.plot(range(10))
ax.remove()

fig2 = plt.figure()
ax.figure=fig2
fig2.axes.append(ax)
fig2.add_axes(ax)

dummy = fig2.add_subplot(111)
ax.set_position(dummy.get_position())
dummy.remove()
plt.close(fig1)

plt.show()

1
小加成:由于关键字而plt.show()被替换fig2.savefig('out.png', dpi=300)为定位时dpi。可以通过dpiax初始化时设置最终值来避免这种情况:fig1, ax = plt.subplots(dpi=300)
Matthias123

在我的Python Shell中,看起来这行没有做任何事情:fig2.axes.append(ax)
Spirko

ax.remove()结果NotImplementedError: cannot remove artist(Python 3.7.0,matplotlib 2.2.2)
gerrit

@gerrit与上面的代码段相比,您进行了任何更改吗?这对我来说可以。
ImportanceOfBeingErnest

1
@irene注意,此解决方案仅将轴移动到新图形,它不设置任何变换。因此,预计会出现此类问题。由于不鼓励在人物之间移动艺术家,因此,如果您需要可靠的输出,最好不要使用它。
ImportanceOfBeingErnest

4

对于线图,您可以处理Line2D对象本身:

fig1 = pylab.figure()
ax1 = fig1.add_subplot(111)
lines = ax1.plot(scipy.randn(10))

fig2 = pylab.figure()
ax2 = fig2.add_subplot(111)
ax2.add_line(lines[0])

+1好榜样。似乎无法将轴创建与图形创建脱钩,但是我可以抓住轴实例并将其传递给新图形。
juanchopanza

1
请注意,此方法不再起作用。请参阅Joe Kington从2012年12月7日起对上述回答的评论。
joelostblom

2
ax2.add_line(lines[0])结果RuntimeError: Can not put single artist in more than one figure(Python 3.7.0,matplotlib 2.2.2)。
Gerrit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.