J'utilise matplotlib pour réaliser des diagrammes de dispersion. Chaque point du nuage de points est associé à un objet nommé. J'aimerais pouvoir voir le nom d'un objet lorsque je passe mon curseur sur le point du nuage de points associé à cet objet. En particulier, il serait agréable de pouvoir voir rapidement le nom des points qui sont des valeurs aberrantes. La chose la plus proche que j'ai pu trouver en cherchant ici est la commande annoter, mais elle semble créer une étiquette fixe sur le graphique. Malheureusement, avec le nombre de points que j'ai, le nuage de points serait illisible si j'étiquetais chaque point. Quelqu'un connaît-il un moyen de créer des étiquettes qui n'apparaissent que lorsque le curseur se trouve à proximité du point en question ?
Réponse
Trop de publicités?
Yanarof Foranay
Points
11
En me basant sur Markus Dutschke" et "ImportanceOfBeingErnest", j'ai (imo) simplifié le code et l'ai rendu plus modulaire.
De plus, cela ne nécessite pas l'installation de paquets supplémentaires.
import matplotlib.pylab as plt
import numpy as np
plt.close('all')
fh, ax = plt.subplots()
#Generate some data
y,x = np.histogram(np.random.randn(10000), bins=500)
x = x[:-1]
colors = ['#0000ff', '#00ff00','#ff0000']
x2, y2 = x,y/10
x3, y3 = x, np.random.randn(500)*10+40
#Plot
h1 = ax.plot(x, y, color=colors[0])
h2 = ax.plot(x2, y2, color=colors[1])
h3 = ax.scatter(x3, y3, color=colors[2], s=1)
artists = h1 + h2 + [h3] #concatenating lists
labels = [list('ABCDE'*100),list('FGHIJ'*100),list('klmno'*100)] #define labels shown
#___ Initialize annotation arrow
annot = ax.annotate("", xy=(0,0), xytext=(20,20),textcoords="offset points",
bbox=dict(boxstyle="round", fc="w"),
arrowprops=dict(arrowstyle="->"))
annot.set_visible(False)
def on_plot_hover(event):
if event.inaxes != ax: #exit if mouse is not on figure
return
is_vis = annot.get_visible() #check if an annotation is visible
# x,y = event.xdata,event.ydata #coordinates of mouse in graph
for ii, artist in enumerate(artists):
is_contained, dct = artist.contains(event)
if(is_contained):
if('get_data' in dir(artist)): #for plot
data = list(zip(*artist.get_data()))
elif('get_offsets' in dir(artist)): #for scatter
data = artist.get_offsets().data
inds = dct['ind'] #get which data-index is under the mouse
#___ Set Annotation settings
xy = data[inds[0]] #get 1st position only
annot.xy = xy
annot.set_text(f'pos={xy},text={labels[ii][inds[0]]}')
annot.get_bbox_patch().set_edgecolor(colors[ii])
annot.get_bbox_patch().set_alpha(0.7)
annot.set_visible(True)
fh.canvas.draw_idle()
else:
if is_vis:
annot.set_visible(False) #disable when not hovering
fh.canvas.draw_idle()
fh.canvas.mpl_connect('motion_notify_event', on_plot_hover)
- Réponses précédentes
- Plus de réponses