gpt4 book ai didi

python - matplotlib 子图之间的箭头

转载 作者:行者123 更新时间:2023-12-05 02:08:32 47 4
gpt4 key购买 nike

我决定尝试一下 this示例代码一点。我能够弄清楚如何在两个子图之间画一条直线,即使该线位于其中一个子图的边界之外。

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np

fig = plt.figure(figsize=(10, 5))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
axs = [ax1, ax2]

# Fixing random state for reproducibility
np.random.seed(19680801)

# generate some random test data
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]

# plot violin plot
axs[0].violinplot(all_data,
showmeans=False,
showmedians=True)
axs[0].set_title('Violin plot')

# plot box plot
axs[1].boxplot(all_data)
axs[1].set_title('Box plot')

# adding horizontal grid lines
for ax in axs:
ax.yaxis.grid(True)
ax.set_xticks([y + 1 for y in range(len(all_data))])
ax.set_xlabel('Four separate samples')
ax.set_ylabel('Observed values')

for tick in ax.xaxis.get_major_ticks():
tick.label.set_fontsize(20)
plt.setp(axs[0], xticklabels=['x1', 'x2', 'x3', 'x4'])

transFigure = fig.transFigure.inverted()
coord1 = transFigure.transform(ax1.transData.transform([5,10]))
coord2 = transFigure.transform(ax2.transData.transform([2,-10]))
line = mpl.lines.Line2D((coord1[0],coord2[0]),(coord1[1],coord2[1]),
c='k', lw=5, transform=fig.transFigure)
fig.lines.append(line)

是的,添加的那行很丑陋,但我只是想让它发挥作用。

但是,我真正想做的是在子图之间制作一个箭头,如果没有陪审团操纵我自己的箭头尾部,我无法弄清楚该怎么做。有没有办法使用 matplotlib.pyplot.arrow 类来做到这一点?

最佳答案

我也想在两个子图之间画一个箭头,但我什至不知道从哪里开始!但是,原始问题中子图示例之间的界线给了我足够的线索来开始......

首先,我将原始问题中的代码简化为一个最小的工作示例:

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()

这会产生以下输出:

Line between subplots

然后,使用 this blog post ,我认为答案是创建一个 matplotlib.patches.FancyArrowPatch 并将其附加到 fig.patches(而不是创建一个 matplotlib.lines.Line2D 并将其附加到 fig.lines)。经咨询matplotlib.patches.FancyArrowPatch documentation ,再加上一些试验和错误,我想出了一些可以在 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 中不起作用,您可以从中得到:

Arrow between subplots - incorrect

请注意,箭头的末端没有与目标点(橙色圆圈)对齐,而它们应该对齐。

这个matplotlib版本的改变也导致原来的行例子以同样的方式失败。

不过,还有更好的补丁!使用 ConnectionPatch ( docs ),它是 FancyArrowPatch 的子类,而不是直接使用 FancyArrowPatch 作为 ConnectionPatch 专门为此用例设计,可以更正确地处理转换,如本 matplotlib documentation example 所示。 :

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.2matplotlib 3.4.2 中产生正确的输出,如下所示:

enter image description here

要在 matplotlib 3.4.2 中绘制连接两个子图的正确定位的线,请使用 ConnectionPatch 如上所述,但使用 arrowstyle="-"(即没有箭头,所以只有一条线)。

注意:您不能使用:

  • plt.arrow 因为它会自动添加到当前轴,所以只出现在一个子图中

  • matplotlib.patches.Arrow 因为轴图变换使箭头倾斜

  • matplotlib.patches.FancyArrow 因为这也会导致箭头倾斜

关于python - matplotlib 子图之间的箭头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60807792/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com