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。可以通过dpi在ax初始化时设置最终值来避免这种情况: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.