我还想在两个子图之间画一个箭头,但我什至不知道从哪里开始!然而,原始问题中子图示例之间的界限给了我足够的线索来开始......
首先,我将原始问题中的代码简化为最小的工作示例:
from matplotlib import lines, pyplot as plt
fig = plt.figure()
# First subplot
ax1 = fig.add_subplot(121)
plt.plot([0, 1], [0, 1])
# Second subplot
ax2 = fig.add_subplot(122)
plt.plot([0, 1], [0, 1])
# Add line from one subplot to the other
xyA = [0.5, 1.0]
ax1.plot(*xyA, "o")
xyB = [0.75, 0.25]
ax2.plot(*xyB, "o")
transFigure = fig.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform(xyA))
coord2 = transFigure.transform(ax2.transData.transform(xyB))
line = lines.Line2D(
(coord1[0], coord2[0]), # xdata
(coord1[1], coord2[1]), # ydata
transform=fig.transFigure,
color="black",
)
fig.lines.append(line)
# Show figure
plt.show()
这会产生以下输出:
然后,使用这篇博文, I thought答案是创建一个matplotlib.patches.FancyArrowPatch
并将其附加到fig.patches
(而不是创建一个matplotlib.lines.Line2D
并将其附加到fig.lines
)。咨询后matplotlib.patches.FancyArrowPatch文档,加上一些试验和错误,我想出了一些可行的东西在 matplotlib 3.1.2 中:
from matplotlib import patches, pyplot as plt
fig = plt.figure()
# First subplot
ax1 = fig.add_subplot(121)
plt.plot([0, 1], [0, 1])
# Second subplot
ax2 = fig.add_subplot(122)
plt.plot([0, 1], [0, 1])
# Add line from one subplot to the other
xyA = [0.5, 1.0]
ax1.plot(*xyA, "o")
xyB = [0.75, 0.25]
ax2.plot(*xyB, "o")
transFigure = fig.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform(xyA))
coord2 = transFigure.transform(ax2.transData.transform(xyB))
arrow = patches.FancyArrowPatch(
coord1, # posA
coord2, # posB
shrinkA=0, # so tail is exactly on posA (default shrink is 2)
shrinkB=0, # so head is exactly on posB (default shrink is 2)
transform=fig.transFigure,
color="black",
arrowstyle="-|>", # "normal" arrow
mutation_scale=30, # controls arrow head size
linewidth=3,
)
fig.patches.append(arrow)
# Show figure
plt.show()
但是,根据下面的评论,这不适用于matplotlib 3.4.2
,你在哪里得到这个:
请注意,箭头的末端没有与目标点(橙色圆圈)对齐,而它们应该对齐。
This matplotlib
版本更改也会导致原始行示例以同样的方式失败。
不过,还有一个更好的补丁!使用ConnectionPatch
(docs),它是一个子类FancyArrowPatch
,而不是使用FancyArrowPatch
直接作为ConnectionPatch
是专门为此用例设计的,可以更正确地处理转换,如下所示matplotlib文档示例:
fig = plt.figure()
# First subplot
ax1 = fig.add_subplot(121)
plt.plot([0, 1], [0, 1])
# Second subplot
ax2 = fig.add_subplot(122)
plt.plot([0, 1], [0, 1])
# Add line from one subplot to the other
xyA = [0.5, 1.0]
ax1.plot(*xyA, "o")
xyB = [0.75, 0.25]
ax2.plot(*xyB, "o")
# ConnectionPatch handles the transform internally so no need to get fig.transFigure
arrow = patches.ConnectionPatch(
xyA,
xyB,
coordsA=ax1.transData,
coordsB=ax2.transData,
# Default shrink parameter is 0 so can be omitted
color="black",
arrowstyle="-|>", # "normal" arrow
mutation_scale=30, # controls arrow head size
linewidth=3,
)
fig.patches.append(arrow)
# Show figure
plt.show()
这会产生正确的输出matplotlib 3.1.2
and matplotlib 3.4.2
,看起来像这样:
要绘制一条正确定位的线连接两个子图matplotlib 3.4.2
, use a ConnectionPatch
如上所述,但与arrowstyle="-"
(即没有箭头,所以只是一条线)。
注意:您不能使用:
-
plt.arrow
因为它会自动添加到当前轴,所以只出现在一个子图中
-
matplotlib.patches.Arrow
当轴图变换使箭头倾斜时
-
matplotlib.patches.FancyArrow
因为这也会导致箭头倾斜