簡體   English   中英

從Pandas DataFrame構造NetworkX圖

[英]Construct NetworkX graph from Pandas DataFrame

我想從一個簡單的Pandas DataFrame創建一些NetworkX圖:

        Loc 1   Loc 2   Loc 3   Loc 4   Loc 5   Loc 6   Loc 7
Foo     0       0       1       1       0       0           0
Bar     0       0       1       1       0       1           1
Baz     0       0       1       0       0       0           0
Bat     0       0       1       0       0       1           0
Quux    1       0       0       0       0       0           0

其中Foo…是索引, Loc 1Loc 7是列。 但轉換為Numpy矩陣或重新排列似乎不適用於為nx.Graph()生成輸入。 是否有實現這一目標的標准策略? 我不反對重新格式化Pandas中的數據 - >轉儲到CSV - >導入到NetworkX,但似乎我應該能夠從索引和值中的節點生成邊緣。

NetworkX期望一個方形矩陣 (節點和邊),或許*你想傳遞它:

In [11]: df2 = pd.concat([df, df.T]).fillna(0)

注意:索引和列的順序是一樣的很重要!

In [12]: df2 = df2.reindex(df2.columns)

In [13]: df2
Out[13]: 
       Bar  Bat  Baz  Foo  Loc 1  Loc 2  Loc 3  Loc 4  Loc 5  Loc 6  Loc 7  Quux
Bar      0    0    0    0      0      0      1      1      0      1      1     0
Bat      0    0    0    0      0      0      1      0      0      1      0     0
Baz      0    0    0    0      0      0      1      0      0      0      0     0
Foo      0    0    0    0      0      0      1      1      0      0      0     0
Loc 1    0    0    0    0      0      0      0      0      0      0      0     1
Loc 2    0    0    0    0      0      0      0      0      0      0      0     0
Loc 3    1    1    1    1      0      0      0      0      0      0      0     0
Loc 4    1    0    0    1      0      0      0      0      0      0      0     0
Loc 5    0    0    0    0      0      0      0      0      0      0      0     0
Loc 6    1    1    0    0      0      0      0      0      0      0      0     0
Loc 7    1    0    0    0      0      0      0      0      0      0      0     0
Quux     0    0    0    0      1      0      0      0      0      0      0     0

In[14]: graph = nx.from_numpy_matrix(df2.values)

這不會將列/索引名稱傳遞給圖表,如果您想這樣做,可以使用relabel_nodes (您可能必須警惕pandas的DataFrames中允許的重復項):

In [15]: graph = nx.relabel_nodes(graph, dict(enumerate(df2.columns))) # is there nicer  way than dict . enumerate ?

*目前尚不清楚所需圖表的列和索引的確切含義。

有點遲到的答案,但現在networkx可以從pandas數據幀中讀取數據 ,在這種情況下,理想情況下,簡單有向圖的格式如下:

+----------+---------+---------+
|   Source |  Target |  Weight |
+==========+=========+=========+
| Node_1   | Node_2  |   0.2   |
+----------+---------+---------+
| Node_2   | Node_1  |   0.6   |   
+----------+---------+---------+

如果您使用鄰接矩陣,那么Andy Hayden是對的,您應該注意正確的格式。 因為在你的問題中你使用0和1,我想你想看到一個無向圖。 這可能看起來違反直覺,因為你說Index代表一個人,而列代表一個給定人所屬的群體 ,但另一方面,群體(成員)屬於一個人也是正確的。 遵循這個邏輯,您實際上應該將組放在索引中,將人員放在列中。

只是旁注:您還可以在有向圖的意義上定義此問題,例如,您希望可視化層次結構類別的關聯網絡。 在那里,例如從Samwise Gamgee到Hobbits的關聯通常比在另一個方向更強(因為Frodo Baggins更可能是Hobbit原型)

您也可以使用scipy來創建方形矩陣,如下所示:

import scipy.sparse as sp

cols = df.columns
X = sp.csr_matrix(df.astype(int).values)
Xc = X.T * X  # multiply sparse matrix
Xc.setdiag(0)  # reset diagonal

# create dataframe from co-occurence matrix in dense format
df = pd.DataFrame(Xc.todense(), index=cols, columns=cols)

稍后,您可以從數據框創建邊緣列表並將其導入Networkx:

df = df.stack().reset_index()
df.columns = ['source', 'target', 'weight']

df = df[df['weight'] != 0]  # remove non-connected nodes

g = nx.from_pandas_edgelist(df, 'source', 'target', ['weight'])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM