【问题标题】:How do I label a specific point in a scatter plot with a unique ID?如何使用唯一 ID 标记散点图中的特定点?
【发布时间】:2017-08-26 04:32:13
【问题描述】:

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

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

  1. 单击鼠标时,检索所选点的 ID。
  2. 将 ID 插入一个黑盒函数,该函数返回附近* ID 的列表。
  3. 突出显示返回列表中 ID 的点。

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

我该怎么做:

  1. 将每个点与一个ID关联,并在单击该点时返回该ID?
  2. 当我只知道它们的 ID 时,突出显示布局中的其他点?
  3. 重新定位各个点,同时保持其各自的组,即与属于不同组/地块的点交换位置。

我在切换到 matplotlib 之前使用了 pyqtgraph,所以我首先想到的是创建一个 ID 及其点对象的字典。用pick_event做实验后,在我看来,点对象的概念在matplotlib中是不存在的。根据我到目前为止所学到的,每个点都由一个索引表示,只有它的 PathCollection 可以返回关于它自己的信息,例如坐标。我还了解到,特定点的颜色修改是通过其PathCollection 完成的,而在 pyqtgraph 中我可以通过点对象来完成,例如point.setBrush('#000000').

【问题讨论】:

标签: python matplotlib


【解决方案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中注册了一个pick事件,一旦点击了一个还不是黑色的点,就会从DataFrame中获取与所选点对应的id。从 id 中,通过“黑盒函数”生成其他 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的点已被点击,其他id为['EDEA', 'DEEA', 'EDAE', 'DEAE']的点已被黑盒功能选中。并非所有这些 ID 都存在,因此具有现有 ID 的其他两个点也会被着色。

【讨论】:

  • 感谢您的示例。我不知道 DataFrames 的功能,因为我以前从未使用过 pandas。
  • 更改DataFrame中的某些xy值后如何更新散点图?
猜你喜欢
  • 1970-01-01
  • 2016-11-13
  • 2012-03-18
  • 2012-10-25
  • 2021-08-16
  • 1970-01-01
  • 2022-01-16
  • 1970-01-01
  • 2016-08-05
相关资源
最近更新 更多