First you can select all annotations, and then use a mask to check for overlap and hide set_visible() . Here is an example:
import numpy as np import pylab as pl import random import string import math random.seed(0) np.random.seed(0) n = 100 labels = ["".join(random.sample(string.ascii_letters, random.randint(4, 10))) for _ in range(n)] x, y = np.random.randn(2, n) fig, ax = pl.subplots() ax.scatter(x, y) ann = [] for i in range(n): ann.append(ax.annotate(labels[i], xy = (x[i], y[i]))) mask = np.zeros(fig.canvas.get_width_height(), bool) fig.canvas.draw() for a in ann: bbox = a.get_window_extent() x0 = int(bbox.x0) x1 = int(math.ceil(bbox.x1)) y0 = int(bbox.y0) y1 = int(math.ceil(bbox.y1)) s = np.s_[x0:x1+1, y0:y1+1] if np.any(mask[s]): a.set_visible(False) else: mask[s] = True
conclusion:

source share