鼠标悬停在图形上的某些点上(旨在在鼠标悬停在某个点上时显示数据)可以显示某些点的数据,而不能显示其他点的数据

时间:2018-07-06 23:25:21

标签: python python-3.x matplotlib mouseover interactive

我对以下绘图代码有一个奇怪的问题:

topfolder="test"
cfeature="READ_COUNT_RNR"

plotsensitives=[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7666666666666667, 0.7666666666666667, 0.6666666666666666, 0.6666666666666666, 0.23333333333333334, 0.23333333333333334, 0.23333333333333334, 0.23333333333333334, 0.16666666666666666, 0.16666666666666666]
plot1mspecificities=[0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7, 0.7, 0.2666666666666667, 0.2666666666666667, 0.23333333333333328, 0.23333333333333328, 0.16666666666666663, 0.16666666666666663]
seed=[57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0]
cutoff=[10.0, 10.0, 30.0, 30.0, 50.0, 50.0, 75.0, 75.0, 100.0, 100.0, 150.0, 150.0, 250.0, 250.0, 500.0, 500.0, 750.0, 750.0, 1000.0, 1000.0]
pangiaver=['test']*20

labels=["{0},{1},{2},{3},{4}".format(round(100*plotsensitives[pos],2),round(100*plot1mspecificities[pos],2),seed[pos],cutoff[pos],pangiaver[pos]) for pos in range(len(plot1mspecificities))]
annotations = [None for label in labels]

import matplotlib.pyplot as plt
import math

##defining size of markers:
markersize = 5
markersize_inches = markersize/72.

fig,ax = plt.subplots()
sc = plt.scatter(plot1mspecificities,plotsensitives)
plt.title('Receiver Operating Characteristic for the feature {0} in the {1} dataset'.format(cfeature,topfolder))
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
trans = ax.transData+fig.dpi_scale_trans.inverted()

##function for checking mouse coordinates and annotating
## need to define xdata,ydata
xdata,ydata=plotsensitives,plot1mspecificities
def on_move(event):
    if event.inaxes:
        x0, y0 = trans.transform((event.xdata, event.ydata))
        #user coordinates=event.xdata, event.ydata, these are values seen by user, plot coordinates x0, y0, unseen coordinates used by plot
        xfig, yfig = zip(*[trans.transform((x,y)) for x,y in zip(xdata,ydata)])
        dists = [math.sqrt((x-x0)**2+(y-y0)**2) for x,y in zip(xfig, yfig)]

        for n,(x,y,dist,label) in enumerate(zip(xdata,ydata,dists, labels)):
            if dist < markersize_inches and annotations[n] is None:
                annotations[n]=ax.annotate(
                    label,
                    [x,y], xycoords='data',
                    xytext = (10,10), textcoords='offset points',
                    ha='left', va='center',
                    bbox=dict(facecolor='white', edgecolor='black', boxstyle='round'),
                    zorder=10,
                )
                fig.canvas.draw()

            elif dist > markersize_inches and annotations[n] is not None:
                annotations[n].remove()
                annotations[n] = None
                fig.canvas.draw()
##connecting the event handler
cid = fig.canvas.mpl_connect('motion_notify_event', on_move)

plt.show()

该图被设计为当鼠标悬停在一个点上时显示标签,并且这种方法有效,但仅适用于某些点。它应该适用于所有点,我看不出为什么它只适用于某些点的明显方法。它是在Ubuntu 16.04的python 3.5上运行的,使用上个月随pip一起安装的matplotlib。

我认为这段代码可以用作模板,以某种方式进行交互,对很多人都有用。如果有人可以找出问题,我将在下面发布完整的固定代码,以便任何人都可以使用它,并给解决它的人员以完整的信誉。我真的很感谢有帮助。

编辑1: 正如@DyZ所指出的,在这里找到一种使标签仅显示坐标信息的解决方案:当将鼠标悬停在matplotlib中的某个点上时,是否可能使标签出现?但是,如果要添加元数据怎么办?

下面是修改了向我指出的解决方案后的代码,如何修复该代码,以使其打印出与数据点有关的5个不同值?

import matplotlib.pyplot as plt

topfolder="test"
cfeature="READ_COUNT_RNR"

plotsensitives=[0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.7666666666666667, 0.7666666666666667, 0.6666666666666666, 0.6666666666666666, 0.23333333333333334, 0.23333333333333334, 0.23333333333333334, 0.23333333333333334, 0.16666666666666666, 0.16666666666666666]
plot1mspecificities=[0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7666666666666666, 0.7, 0.7, 0.2666666666666667, 0.2666666666666667, 0.23333333333333328, 0.23333333333333328, 0.16666666666666663, 0.16666666666666663]
seed=[57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0, 57.0, 75.0]
cutoff=[10.0, 10.0, 30.0, 30.0, 50.0, 50.0, 75.0, 75.0, 100.0, 100.0, 150.0, 150.0, 250.0, 250.0, 500.0, 500.0, 750.0, 750.0, 1000.0, 1000.0]
pangiaver=['test']*20

tempdata=[[round(100*entry,2) for entry in plot1mspecificities],[round(100*entry,2) for entry in plotsensitives],seed,cutoff,pangiaver]
transposeddata=list(map(list,zip(*tempdata)))

fig,ax = plt.subplots()
sc = plt.scatter(plot1mspecificities,plotsensitives, s=10) #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]]
    alldatafrompoint=transposeddata[ind["ind"][0]]
    annot.xy = alldatafrompoint
    text=("{}, "*len(pos))[:-2].format(*alldatafrompoint)
    annot.set_text(text)

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()

编辑2: 使用matplotlib在鼠标上的散点图上用x,y坐标以外的其他标签标记点的方法似乎是一个不错的解决方案,但可以扩展到很多点,尽管实际上需要可能不需要用弹出标签查看10000点。

0 个答案:

没有答案