在matplotlib中使用mpldatacursor的工具提示

时间:2018-06-13 15:21:39

标签: python matplotlib

我已经把头发拉了一会儿。我正在尝试使用mpldatacursormatplotlib来提供散点图上的工具提示功能。每个点都有一些与之关联的数据,我希望在点击该点时显示这些数据。

这是一个最小的(不是)工作示例:

import numpy as np
import mpldatacursor
import string
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as mpl

nations = ['Russia', 'America', 'China', 'France']
data = list()
idx = list()

np.random.seed(42) #Seed for repeatability

# Random data
for (id, nation) in enumerate(nations):
    for i in range(0,10):
        data.append((id+1)*np.random.random((2,1)))
        name = list(string.ascii_uppercase[20:])
        np.random.shuffle(name)
        idx.append(nation + '-' + ''.join(name))

mpl.figure()
data = np.squeeze(np.asarray(data))
m, n = 0, 9

# Plot by group
for (id,nation) in enumerate(nations):
    mpl.scatter(data[m:n,0] , data[m:n,1] , label=nation)
    m = n + 1
    n += 10

formatter = lambda **kwargs: ', '.join(kwargs['point_label'])
mpl.legend()
mpldatacursor.datacursor(formatter=formatter, point_labels=idx)
mpl.show(block=True)

但是当我这样做时,工具提示与传说不符。此外,只有以RussiaUSA开头的标签会显示在图中。我做错了什么?

enter image description here

3 个答案:

答案 0 :(得分:2)

问题是,componentDidMount(){ const mychart = new Chartist.Line('.ct-chart', data); } 每次调用scatter都会创建一个新的艺术家对象。解决方法基于source code中的doc字符串。

  

point_labels:sequence或dict,可选               艺术家“子项目”的标签,传递给格式化程序               作为matplotlib kwarg运行。可能是单身               序列(用于所有艺术家)或艺术家的词典:序列对。

它确实涉及导入受保护的matplotlib模块/成员。这看起来像我想要的那样:

point_label

答案 1 :(得分:1)

假设您只是想要名字,如果您将mpldatacursor.datacursor来电更改为使用'{label}',就像mpldatacursor网站上的第一个example一样,这似乎正常/ p>

mpldatacursor.datacursor(formatter='{label}'.format)

我认为问题出在kwargs和lambda函数上。如果您想在工具提示中获得更多数据,最好将其添加到plt.scatter上的标签上,对每个点使用单独的调用,例如

import numpy as np
import mpldatacursor
import string
import matplotlib
matplotlib.use('Qt5Agg')
from matplotlib import pyplot as plt

nations = ['Russia', 'America', 'China', 'France']
cDict =  {'Russia':'r', 'America':'b', 'China':'g', 'France':'c'}

np.random.seed(42) #Seed for repeatability

# Random data
for (id, nation) in enumerate(nations):
    for i in range(0,10):
        x = (id+1)*np.random.random((2,1))
        name = list(string.ascii_uppercase[20:])
        np.random.shuffle(name)
        plt.scatter(x[0], x[1], c=cDict[nation], label=nation + '-' + ''.join(name))

mpldatacursor.datacursor(formatter='{label}'.format)
plt.show(block=True)

答案 2 :(得分:1)

通常,您可以将数据放在表格中,或者为了示例,您可以使用多个列表。因此,可能会从数据列创建单个散点图,并使用名称到数字的映射来创建散点图中的颜色。

然后,可以使用matplotlib pick_event从相应列表中获取数据,给定点击发生点的索引。

这一切都不需要任何外部软件包,如datacursor。

import numpy as np; np.random.seed(42)
import string
from matplotlib import pyplot as plt

nations = ['Russia', 'America', 'China', 'France']

#Create lists data, nat, idx
nat = np.random.choice(nations, 50)
data = np.random.rand(50,2)
strings = ["".join(np.random.choice(list(string.ascii_uppercase), 7)) for _ in range(50)]
idx = ["{}-{}".format(n,w) for n,w in zip(nat,strings)]

labels, i = np.unique(nat, return_inverse=True)

fig, ax = plt.subplots()


scatter = ax.scatter(data[:,0], data[:,1], c=i, cmap="RdYlGn", picker=5)

rect = lambda c: plt.Rectangle((0,0),1,1, color=scatter.cmap(scatter.norm(c)))
handles = [rect(c) for c in np.unique(i)]
plt.legend(handles, labels)

#Create annotation
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)

#Create event handler
def onpick(evt):
    if evt.artist == scatter:
        ind = evt.ind[0]
        annot.xy = (data[ind])
        annot.set_text(idx[ind])
        annot.set_visible(True)
    if evt.mouseevent.button == 3:
        annot.set_visible(False)
    fig.canvas.draw_idle()

fig.canvas.mpl_connect("pick_event", onpick)

plt.show()

enter image description here