首页 > 解决方案 > 使用具有不同范围图的 mark_inset

问题描述

假设我想将一个图插入到一个图形中,但插图的轴范围与我标记插图的轴范围不同。例如:

fig, ax = plt.subplots()
axins = inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
axins.set_xlim(x1, x2) # apply the x-limits
axins.set_ylim(y1, y2) # apply the y-limits

plt.xticks(visible=False)
plt.yticks(visible=False)

mark_inset(ax, axins, loc1=4, loc2=1)#, fc="none")#, ec="0.5")

结果是一个空的插图:

在此处输入图像描述

但这很明显,因为我将x和设置为不通过y的范围。x**3我想看到的是,例如,插入图中的x**3for 0to1的图,而 mark_inset 仍将“缩放”到上面框出的区域,该区域具有不同的范围。

我怎样才能做到这一点?

标签: pythonmatplotlib

解决方案


在这种情况下,您不能mark_inset直接使用,因为这正是该函数所做的:将标记与插图的轴限制同步。

使用矩形

相反,您可以将某个矩形放置在您想要的任何位置,并使用ConnectionPatches 在插图和矩形之间绘制一些线。

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as il
import matplotlib.patches as mpatches

fig, ax = plt.subplots()

axins = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
rect = mpatches.Rectangle((x1,y1), width=x2-x1, height=y2-y1, facecolor="None", edgecolor="k", linewidth=0.8)
fig.canvas.draw()
p1 = mpatches.ConnectionPatch(xyA=(1,0), xyB=(x2,y1), coordsA="axes fraction", coordsB="data",  axesA=axins, axesB=ax)
p2 = mpatches.ConnectionPatch(xyA=(1,1), xyB=(x2,y2), coordsA="axes fraction", coordsB="data",  axesA=axins, axesB=ax)

ax.add_patch(rect)
ax.add_patch(p1)
ax.add_patch(p2)

plt.show()

使用虚拟轴

您也可以简单地添加一个额外的插图,只是为了mark_inset与它一起使用。

import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.axes_grid1.inset_locator as il

fig, ax = plt.subplots()
axins_dummy = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)
axins = il.inset_axes(ax, 1,1 , loc=2, bbox_to_anchor=(0.35,0.85),bbox_transform=ax.figure.transFigure)

x = np.linspace(0, 3, 100)
y = x**2
ax.plot(x, y)
axins.plot(x, x**3)

x1, x2, y1, y2 = 2.,3, 6, 8 # specify the limits
axins_dummy .set_xlim(x1, x2) # apply the x-limits
axins_dummy .set_ylim(y1, y2) # apply the y-limits

axins_dummy.tick_params(left=False, bottom=False, labelleft=False, labelbottom=False )

il.mark_inset(ax,axins_dummy , loc1=4, loc2=1)#, fc="none")#, ec="0.5")

plt.show()

在这两种情况下,结果图看起来像

在此处输入图像描述

也许值得注意的是,结果图当然是不正确的。任何读者都会认为插图显示了曲线的一部分,但事实并非如此。因此,请确保不要在出版物或报告中使用此类图表。


推荐阅读