Adding Hovering Annotations to Scatter Plots
When using matplotlib to create scatter plots where each point represents a specific object, it can be helpful to display the object's name when the cursor hovers over the corresponding point. This allows users to quickly identify outliers or other relevant information without cluttering the plot with permanent labels.
One solution involves using the annotate function to create a label that becomes visible when the cursor hovers over a specific point. Here is an example code snippet:
import matplotlib.pyplot as plt import numpy as np; np.random.seed(1) x = np.random.rand(15) y = np.random.rand(15) names = np.array(list("ABCDEFGHIJKLMNO")) c = np.random.randint(1, 5, size=15) norm = plt.Normalize(1, 4) cmap = plt.cm.RdYlGn fig, ax = plt.subplots() sc = plt.scatter(x, y, c=c, s=100, cmap=cmap, norm=norm) 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 update_annot(ind): pos = sc.get_offsets()[ind["ind"][0]] annot.xy = pos text = "{}, {}".format(" ".join(list(map(str, ind["ind"]))), " ".join([names[n] for n in ind["ind"]])) annot.set_text(text) annot.get_bbox_patch().set_facecolor(cmap(norm(c[ind["ind"][0]]))) annot.get_bbox_patch().set_alpha(0.4) def hover(event): vis = annot.get_visible() if event.inaxes == ax: cont, ind = sc.contains(event) if cont: update_annot(ind) annot.set_visible(True) fig.canvas.draw_idle() else: if vis: annot.set_visible(False) fig.canvas.draw_idle() fig.canvas.mpl_connect("motion_notify_event", hover) plt.show()
This code defines a scatter plot with 15 random points. Each point is associated with a name from the names array. The annotate function creates a label that initially remains invisible.
The hover function is defined to handle mouse movement events. When the cursor hovers over a point, it checks if the point is contained within the scatter plot. If so, it updates the annotation with the object's name and position, makes it visible, and redraws the figure. When the cursor leaves the point, the annotation is hidden.
For line plots instead of scatter plots, the same solution can be adapted as follows:
import matplotlib.pyplot as plt import numpy as np; np.random.seed(1) x = np.sort(np.random.rand(15)) y = np.sort(np.random.rand(15)) names = np.array(list("ABCDEFGHIJKLMNO")) norm = plt.Normalize(1, 4) cmap = plt.cm.RdYlGn fig, ax = plt.subplots() line, = plt.plot(x, y, marker="o") 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 update_annot(ind): x, y = line.get_data() annot.xy = (x[ind["ind"][0]], y[ind["ind"][0]]) text = "{}, {}".format(" ".join(list(map(str, ind["ind"]))), " ".join([names[n] for n in ind["ind"]])) annot.set_text(text) annot.get_bbox_patch().set_alpha(0.4) def hover(event): vis = annot.get_visible() if event.inaxes == ax: cont, ind = line.contains(event) if cont: update_annot(ind) annot.set_visible(True) fig.canvas.draw_idle() else: if vis: annot.set_visible(False) fig.canvas.draw_idle() fig.canvas.mpl_connect("motion_notify_event", hover) plt.show()
The above is the detailed content of How can I add hovering annotations to Matplotlib scatter and line plots to display object names on mouseover?. For more information, please follow other related articles on the PHP Chinese website!