我有一个带有许多点的散点图。每个点都有一个与之相关的字符串(长度不一样),我想提供一个标签,但我不能适应它们。所以我想迭代我的数据点从最重要到最不重要,并且在每种情况下仅在标签不与现有标签重叠时才应用标签。琴弦长度不一。其中一位评论者提到解决背包问题以找到最佳解决方案。在我的情况下,贪心算法(总是标记可以被标记而没有重叠的最重要的剩余点)将是一个良好的开端并且可能就足够了。
这是一个玩具示例。我可以让Python只标记尽可能多的点而不重叠吗?
import matplotlib.pylab as plt, numpy as np
npoints = 100
xs = np.random.rand(npoints)
ys = np.random.rand(npoints)
plt.scatter(xs, ys)
labels = iter(dir(np))
for x, y, in zip(xs, ys):
# Ideally I'd condition the next line on whether or not the new label would overlap with an existing one
plt.annotate(labels.next(), xy = (x, y))
plt.show()
答案 0 :(得分:9)
您可以先绘制所有注释,然后使用蒙版数组检查重叠并使用set_visible()
隐藏。这是一个例子:
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
输出:
答案 1 :(得分:0)
请注意:为了使我的代码正常工作,我必须向renderer=fig.canvas.get_renderer()
方法添加附加的get_window_extent()
参数,而不是默认的get_window_extent(renderer=None)
。我认为此附加参数规范的必要性取决于操作系统。 https://github.com/matplotlib/matplotlib/issues/10874