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

时间:2017-08-25 15:09:24

标签: python matplotlib

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

Sample layout

每个点都有一个唯一的ID,通常是组的一部分。每个组都有自己的颜色,因此我使用多个散点图来创建整个布局。当我点击一个点时,我需要进行以下操作:

  1. 单击鼠标,检索所选点的ID。
  2. 将ID插入黑匣子功能,该功能会返回附近的* ID列表。
  3. 突出显示返回列表中的ID点。

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

  4. 我如何:

    1. 将每个点与ID相关联,并在点击该点时返回ID?
    2. 当我所知道的是他们的ID时,突出显示布局中的其他点?
    3. 在保持各自的组的同时重新定位各个点,即用属于不同组/图的点交换位置。
    4. 我在切换到matplotlib之前使用了pyqtgraph,所以我首先考虑创建一个ID及其点对象的字典。在尝试pick_event之后,在我看来,matplotlib中不存在点对象的概念。根据我迄今为止所学到的知识,每个点都由索引表示,只有PathCollection可以返回有关自身的信息,例如:坐标。我还了解到特定点的颜色修改是通过其PathCollection完成的,而在pyqtgraph中我可以通过点对象来完成。 point.setBrush('#000000')

1 个答案:

答案 0 :(得分:1)

我仍然相信使用单个散点图将是更好的选择。问题中没有任何内容会与此相矛盾。

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

   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列中的颜色从中创建散点图。

选择事件在this previous question中注册,并且一旦点击了一个尚未成为黑色的点,就会获得与所选点对应的DataFrame中的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()

在下图中,点击了身份DAEE的点,黑匣子选择了其他带有ids ['EDEA','DEEA','EDAE','DEAE']的点功能。并非所有这些ID都存在,因此具有现有ID的其他两个点也会着色。

enter image description here

相关问题