2017-08-25 117 views
1

我創建了一個佈局看起來很像這個互動式圖表:如何使用唯一ID標記散點圖中的特定點?

Sample layout

每個點都有一個唯一的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')

+0

有matplotlib的onclick事件:https://matplotlib.org/users/event_handling.html – Moritz

回答

1

我仍然堅信使用單散點圖將是更好的選擇。這個問題中沒有任何東西會與此相矛盾。

您可以將所有數據合併到一個DataFrame中,並將其列爲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列中的顏色從中創建散點圖。

this previous question中註冊挑選事件,並且一旦點擊了一個不是黑色的點,就獲得與所選點對應的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點已經被點擊,並且其它點與IDS [「EDEA」,「DEEA」,「EDAE」,「DEAE」]已經由黑盒選擇功能。並非所有這些ID都存在,因此其他兩個帶有現有ID的點也會着色。

enter image description here

+0

感謝您的例子。我沒有意識到DataFrames的功能,因爲我之前從未使用熊貓。 – FatHippo

+0

如何在更改DataFrame中的某些xy值之後更新散點圖? – FatHippo