[英]Arrows between matplotlib subplots
我決定稍微玩一下這個示例代碼。 我能夠弄清楚如何在兩個子圖之間畫一條直線,即使這條線超出了其中一個子圖的邊界。
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()
這會產生以下輸出:
然后,使用這篇博客文章,我認為答案是創建一個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
不起作用,在那里你得到這個:
請注意,箭頭的末端未與目標點(橙色圓圈)對齊,而這是它們應該對齊的。
此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
和matplotlib 3.4.2
產生正確的輸出,如下所示:
要在matplotlib 3.4.2
繪制連接兩個子圖的正確定位的線,請使用上面的ConnectionPatch
但使用arrowstyle="-"
(即沒有箭頭,所以只有一條線)。
注意:您不能使用:
plt.arrow
因為它會自動添加到當前軸,所以只出現在一個子圖中
matplotlib.patches.Arrow
作為軸圖變換傾斜箭頭
matplotlib.patches.FancyArrow
因為這也會導致傾斜的箭頭
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.