当有多个子图时,matplotlib 的 InsetPosition 出现问题

trouble with matplotlib's InsetPosition when having more than one subplots

我正在用 3 个子图制作这张图,我希望每个子图都有一个插入轴,但使用我的代码,它只会为最后一个子图创建插入轴。你能帮我解决这个问题吗?谢谢

import pylab as pl
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

def test(ax_main, pos, Data):
    ax2 = pl.axes([0, 0, 1, 1])
    ip = InsetPosition(ax_main, pos)
    ax2.set_axes_locator(ip)
    pl.hist(Data)

for i in range(3):
    ax=pl.subplot(1,3,i+1)
    Data = pl.rand(100)
    ax.plot(Data)
    test(ax, [.3,.3,.6,.6], Data)

here is the result: (picture)

编辑:

我可以使用 inset_axes 来解决这个问题:

from mpl_toolkits.axes_grid.inset_locator import inset_axes
def test(ax_main, pos, Data):
    ax2 = inset_axes(ax_main, weight=pos[2], height=pos[3])  # weight and height are not important here because they will be changed in the next lines
    ip = InsetPosition(ax_main, pos)
    ax2.set_axes_locator(ip)
    pl.hist(Data)

for i in range(3):
    ax=pl.subplot(1,3,i+1)
    Data = pl.rand(100)
    ax.plot(Data)
    test(ax, [.3,.3,.6,.6], Data)

这里有两个问题。第一个很好理解。正如 documentation of figure.add_axes 所说:

If the figure already has an axes with the same parameters, then it will simply make that axes current and return it. This behavior has been deprecated as of Matplotlib 2.1. Meanwhile, if you do not want this behavior (i.e., you want to force the creation of a new Axes), you must use a unique set of args and kwargs. The axes label attribute has been exposed for this purpose: if you want two axes that are otherwise identical to be added to the figure, make sure you give them unique labels.

这意味着如果你多次调用plt.axes([0, 0, 1, 1]),它终究不会创建一个新的轴。解决方案是添加标签,例如通过将循环变量 i 与数据一起提供给函数并调用

plt.axes([0, 0, 1, 1], label=str(i))

不幸的是,这还不够,上面的方法仍然不能按预期工作。这对我来说是无法理解的。然而,通过反复试验,人们可能会发现对轴的初始位置使用不同的坐标可以做到这一点。下面我使用 ax2 = plt.axes([0.0, 0.0, 0.1, 0.1], label=str(i)),但是例如[0.2, 0.0, 0.5, 0.1] 似乎也有效,而 [0.2, 0.2, 0.5, 0.1] 无效。更奇怪的是,[0.0, 0.2, 0.5, 0.1] 会在第二个和第三个图中创建一个插图,但不会在第一个图中创建。

所有这些似乎有点武断,但足以解决问题:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

def test(ax_main, pos, Data,i):
    ax2 = plt.axes([0.0, 0.0, 0.1, 0.1], label=str(i))
    ip = InsetPosition(ax_main, pos)
    ax2.set_axes_locator(ip)
    ax2.plot(Data)


for i in range(3):
    ax=plt.subplot(1,3,i+1)
    test(ax, [.3,.3,.6,.6], [1,2], i)

plt.show()