Python 如何使用唯一ID标记散点图中的特定点?

Python 如何使用唯一ID标记散点图中的特定点?,python,matplotlib,Python,Matplotlib,我正在为一个布局创建一个交互式图形,它看起来非常像这样: 每个点都有一个唯一的ID,通常是组的一部分。每个组都有自己的颜色,所以我使用多个散点图来创建整个布局。我需要在单击单个点时发生以下情况: 单击鼠标,检索选定点的ID 将ID插入一个黑盒函数,该函数返回附近*ID的列表 突出显示返回列表中ID的点 *有些ID可能来自不同的组/图 我如何: 是否将每个点与ID关联,并在单击该点时返回ID 当我只知道它们的ID时,突出显示布局中的其他点 重新定位各个点,同时保持其各自的组,即与属于不同组/图的

我正在为一个布局创建一个交互式图形,它看起来非常像这样:

每个点都有一个唯一的ID,通常是组的一部分。每个组都有自己的颜色,所以我使用多个散点图来创建整个布局。我需要在单击单个点时发生以下情况:

  • 单击鼠标,检索选定点的ID
  • 将ID插入一个黑盒函数,该函数返回附近*ID的列表
  • 突出显示返回列表中ID的点

    *有些ID可能来自不同的组/图

  • 我如何:

  • 是否将每个点与ID关联,并在单击该点时返回ID
  • 当我只知道它们的ID时,突出显示布局中的其他点
  • 重新定位各个点,同时保持其各自的组,即与属于不同组/图的点交换位置
    在切换到matplotlib之前,我使用了pyqtgraph,因此我首先想到创建一个ID及其点对象的字典。在试用了
    pick_event
    之后,我觉得matplotlib中似乎不存在点对象的概念。据我目前所知,每个点都由一个索引表示,只有它的
    PathCollection
    可以返回关于自身的信息,例如坐标。我还了解到,特定点的颜色修改是通过其
    路径集合来完成的,而在pyqtgraph中,我可以通过点对象来完成,例如
    point.setBrush(“#000000”)
    我仍然相信使用单个散点图将是更好的选择。这个问题中没有与之相矛盾的东西

    您可以将所有数据合并到一个数据框中,其中包含
    group、id、x、y、color列
    。下面代码中说“创建一些数据集”的部分确实创建了这样一个数据帧

       group    id  x  y       color
    0      1  AEBB  0  0   palegreen
    1      3  DCEB  1  0        plum
    2      0  EBCC  2  0  sandybrown
    3      0  BEBE  3  0  sandybrown
    4      3  BEBB  4  0        plum
    
    请注意,每个组都有自己的颜色。然后可以使用
    color
    列中的颜色从中创建散点

    将拾取事件注册为in,一旦单击一个点(该点尚未为黑色),将从与所选点对应的数据帧中获取
    id
    。根据该id,通过“blackbox函数”生成其他id,并为通过这种方式获得的每个id确定数据帧中点的相应索引。因为我们有一个散点,所以这个索引直接是散点中点的索引(
    PathCollection
    ),我们可以把它画成黑色

    import numpy as np; np.random.seed(1)
    import pandas as pd
    import matplotlib.pyplot as plt
    import matplotlib.colors
    
    ### create some dataset
    x,y = np.meshgrid(np.arange(20), np.arange(20))
    group = np.random.randint(0,4,size=20*20)
    l = np.array(np.meshgrid(list("ABCDE"),list("ABCDE"),
                         list("ABCDE"),list("ABCDE"))).T.reshape(-1,4)
    ide = np.random.choice(list(map("".join, l)), size=20*20, replace=False)
    df = pd.DataFrame({"id" : ide, "group" : group ,
                       "x"  : x.flatten(), "y"  : y.flatten() }) 
    colors = ["sandybrown", "palegreen", "paleturquoise", "plum"]
    df["color"] = df["group"]
    df["color"].update(df["color"].map(dict(zip(range(4), colors ))))
    print df.head()
    
    ### plot a single scatter plot from the table above
    fig, ax = plt.subplots()
    scatter = ax.scatter(df.x,df.y, facecolors=df.color, s=64, picker=4)
    
    
    def getOtherIDsfromID(ID):
        """ blackbox function: create a list of other IDs from one ID """
        l = [np.random.permutation(list(ID)) for i in range(5)]
        return list(set(map("".join, l)))
    
    
    def select_point(event):
        if event.mouseevent.button == 1:
            facecolor = scatter._facecolors[event.ind,:]
            if (facecolor == np.array([[0, 0, 0, 1]])).all():
                c = df.color.values[event.ind][0]
                c = matplotlib.colors.to_rgba(c)
                scatter._facecolors[event.ind,:] = c
            else:
                ID = df.id.values[event.ind][0]
                oIDs = getOtherIDsfromID(ID)
                # for each ID obtained, make the respective point black.
                rows = df.loc[df.id.isin([ID] + oIDs)]
                for i, row in rows.iterrows():
                    scatter._facecolors[i,:] = (0, 0, 0, 1)
                tx = "You selected id {}.\n".format(ID)
                tx += "Points with other ids {} will be affected as well"
                tx = tx.format(oIDs)
                print tx
    
            fig.canvas.draw_idle()
    
    fig.canvas.mpl_connect('pick_event', select_point)
    
    plt.show()
    
    在下图中,已单击id为
    DAEE
    的点,blackbox函数已选择id为['EDEA','DEEA','EDAE','DEAE']的其他点。并非所有这些id都存在,因此具有现有id的另外两个点也会着色


    这里有matplotlib onclick事件:谢谢您的示例。我不知道数据帧的功能,因为我以前从未使用过熊猫。在更改数据帧中的某些xy值后,如何更新散点图?