Annotate multiple dots with one text in matplotlib

I want to use a single text annotation to annotate multiple data points with a few arrows. I made an easy way:

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

Result of the following result: enter image description here

But I don’t really like it because it is ... well, an ugly dirty hack.

In addition, this affects the appearance of the annotation (mainly if translucent bbox, etc. are used).

So, if someone has a real solution, or at least the idea of ​​implementing it, share it.

+6
source share
2 answers

I think the right solution will take too much effort - subclassing _AnnotateBase and adding support for a few arrows. But I managed to fix this problem with a second annotate that affects the look and feel by simply adding alpha=0.0 . So, the updated solution is here if no one provides anything better:

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

Resulting Image: enter image description here

+13
source

Personally, I would like to use the coordinates of the fractions with the coordinates of the axis to guarantee the placement of the text label, and then make all but one label visible, playing with the color keyword argument.

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

Show example plot

+1
source

All Articles