在Matplotlib中,如何使用一个文本注释多个点?

13

我想使用单个注释文本用多个箭头注释多个数据点。我做了一个简单的解决方法:

ax = plt.gca()
ax.plot([1,2,3,4],[1,4,2,6])
an1 = ax.annotate('Test',
  xy=(2,4), xycoords='data',
  xytext=(30,-80), textcoords='offset points',
  arrowprops=dict(arrowstyle="-|>",
                  connectionstyle="arc3,rad=0.2",
                  fc="w"))
an2 = ax.annotate('Test',
  xy=(3,2), xycoords='data',
  xytext=(0,0), textcoords=an1,
  arrowprops=dict(arrowstyle="-|>",
                  connectionstyle="arc3,rad=0.2",
                  fc="w"))
plt.show()

生成以下结果: 在此输入图片描述

但我并不喜欢这种解决方案,因为它是一个丑陋的、肮脏的hack。

此外,它会影响注释的外观(主要是如果使用半透明的边框等)。

因此,如果有人有一个实际的解决方案或者至少知道如何实现它,请分享。


这个问题已经解决了: https://stackoverflow.com/questions/17414010/how-can-i-have-one-annotation-pointing-to-several-points-in-matplotlib - eln05
这正是我在问题中使用的“解决方案”。它会影响文本的可视化效果,因为它会在相同的位置倾倒相同的文本。如果你在那里使用半透明元素,你会最容易注意到它。 - MnZrK
2个回答

17

我猜想正确的解决方案需要太多的努力-通过子类化_AnnotateBase并自己添加支持多个箭头的功能。但是我成功地通过添加alpha=0.0来消除了第二次注释影响视觉外观的问题。如果没有人提供更好的解决方案,这里更新的解决方案如下:

def my_annotate(ax, s, xy_arr=[], *args, **kwargs):
  ans = []
  an = ax.annotate(s, xy_arr[0], *args, **kwargs)
  ans.append(an)
  d = {}
  try:
    d['xycoords'] = kwargs['xycoords']
  except KeyError:
    pass
  try:
    d['arrowprops'] = kwargs['arrowprops']
  except KeyError:
    pass
  for xy in xy_arr[1:]:
    an = ax.annotate(s, xy, alpha=0.0, xytext=(0,0), textcoords=an, **d)
    ans.append(an)
  return ans

ax = plt.gca()
ax.plot([1,2,3,4],[1,4,2,6])
my_annotate(ax,
            'Test',
            xy_arr=[(2,4), (3,2), (4,6)], xycoords='data',
            xytext=(30, -80), textcoords='offset points',
            bbox=dict(boxstyle='round,pad=0.2', fc='yellow', alpha=0.3),
            arrowprops=dict(arrowstyle="-|>",
                            connectionstyle="arc3,rad=0.2",
                            fc="w"))
plt.show()

生成的图片: 在此输入图像描述


2
你应该接受这个答案(你可以回答自己的问题,没关系)。 - Burhan Khalid
我知道,但是stackoverflow不允许我这样做 :) 我需要等待2天或者更长时间。 - MnZrK

2

个人建议使用设置坐标轴分数来保证文本标签的位置,然后通过调整颜色关键字参数使除一个标签外的所有标签都可见。

ax = plt.gca()
ax.plot([1,2,3,4],[1,4,2,6])
label_frac_x = 0.35
label_frac_y = 0.2

#label first point
ax.annotate('Test', 
  xy=(2,4), xycoords='data', color='white',
  xytext=(label_frac_x,label_frac_y), textcoords='axes fraction',
  arrowprops=dict(arrowstyle="-|>",
                  connectionstyle="arc3,rad=0.2",
                  fc="w"))

#label second point    
ax.annotate('Test', 
      xy=(3,2), xycoords='data', color='black',
      xytext=(label_frac_x, label_frac_y), textcoords='axes fraction',
      arrowprops=dict(arrowstyle="-|>",
                      connectionstyle="arc3,rad=0.2",
                      fc="w"))
plt.show()

View Example Plot


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接