Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用matplotlib的非重叠散点图标签_Python_Matplotlib_Scatter Plot - Fatal编程技术网

Python 使用matplotlib的非重叠散点图标签

Python 使用matplotlib的非重叠散点图标签,python,matplotlib,scatter-plot,Python,Matplotlib,Scatter Plot,我有一个有很多点的散点图。每个点都有一个与之相关联的字符串(长度不同),我想提供一个标签,但我不能将它们全部放进去。所以我想从最重要的到最不重要的遍历我的数据点,并且在每种情况下应用一个标签,前提是它不会与现有标签重叠。这些弦的长度各不相同。其中一位评论者提到解决背包问题以找到最佳解决方案。在我的例子中,贪婪算法(总是标记最重要的剩余点,可以不重叠地标记)将是一个良好的开端,可能就足够了 这里有一个玩具的例子。我能让Python只标记尽可能多的点而不重叠吗 import matplotlib.p

我有一个有很多点的散点图。每个点都有一个与之相关联的字符串(长度不同),我想提供一个标签,但我不能将它们全部放进去。所以我想从最重要的到最不重要的遍历我的数据点,并且在每种情况下应用一个标签,前提是它不会与现有标签重叠。这些弦的长度各不相同。其中一位评论者提到解决背包问题以找到最佳解决方案。在我的例子中,贪婪算法(总是标记最重要的剩余点,可以不重叠地标记)将是一个良好的开端,可能就足够了

这里有一个玩具的例子。我能让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()

您可以先绘制所有注释,然后使用遮罩数组检查重叠,并使用
set\u 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
输出:


作为补充说明:为了使代码正常工作,我必须向
get\u window\u extent()
方法添加和添加
renderer=fig.canvas.get\u renderer()
参数,而不是默认的
get\u window\u extent(renderer=None)
。我认为这个附加参数规范的必要性取决于操作系统

简而言之,不,这不是内置的(无论如何,找到最佳的标签集对我来说是背包问题的一种变化…)。您可能会跟踪添加的所有文本,然后检查BBox是否重叠,但是文本对象在绘制之前不知道它们有多大,因此这可能会非常昂贵。您可能会找到实现这种自动标签放置所需的一切。但这并不是小事,你说画文本框来找出它们有多大是“昂贵的”。你是指计算时间吗?我现在有了代码,可以标记所有只需要一两秒钟就可以运行的点。即使是我最棘手的用例也只有几千点。足够公平的重新计算时间。文本渲染是一个瓶颈,但我想尝试做动画/实时绘图,就人类时间而言,它仍然相当快。在我打字之前我应该多想想。这太棒了,谢谢!!其他相关方注意:这是通过Spyder使用IPython实现的,但为了在PyCharm中实现,我必须在
fig.canvas.draw()上方添加一行
pl.tight_layout()
。我从他那里得到了暗示。