NetworkX 提供了便捷的函式來處理不同格式的網路資料,例如 read_edgelist() 可以讀取邊列表,read_adjlist() 可以讀取鄰接列表,write_gexf() 可以將網路資料儲存為 GEXF 格式。這些函式支援讀取和寫入節點和邊的屬性,例如權重、顏色或縮寫,方便進行更細緻的網路分析和視覺化。透過 G.edges(data=True) 和 G.nodes(data=True) 可以存取這些屬性,並將其應用於網路圖的繪製,例如設定邊的顏色或節點的大小。此外,文章還介紹瞭如何從文字資料構建詞共現網路,以及如何使用 NetworkX 建立和分析關聯網路,例如電影演員和電影之間的關係。關聯網路可以透過投影操作轉換為單一型別的網路,方便分析特定型別節點之間的關係。
從資料到網路:網路資料格式與屬性處理
在網路分析中,正確地讀取和寫入網路資料至關重要。NetworkX 提供了多種格式來處理網路資料,包括邊列表(edge list)、鄰接列表(adjacency list)以及 GEXF 格式等。每種格式都有其特定的應用場景和優缺點。
邊列表格式與屬性處理
邊列表是一種常見的網路資料表示方式,其中每行代表一條邊,通常包含源節點、目標節點以及可選的邊屬性。以下是一個簡單的邊列表範例:
Winegroom Uptown 1 red
Winegroom Strawshop 5 orange
Uptown Strawshop 9 blue
Uptown Amazelake 6 red
Strawshop Province 3 orange
在這個範例中,每行不僅定義了節點之間的連線,還包含了邊的權重(weight)和顏色(color)屬性。要讀取這種包含屬性的邊列表,可以使用 read_edgelist() 函式並傳遞 data 引數:
G = nx.read_edgelist(data_dir / 'attributes.edgelist', data=[('weight', float), ('color', str)])
讀取後,可以透過遍歷 G.edges(data=True) 來提取邊的屬性,例如顏色,並將其用於網路視覺化:
colors = [d['color'] for s, t, d in G.edges(data=True)]
nx.draw_networkx(G, width=4, edge_color=colors)
plt.gca().margins(0.15, 0.15)
內容解密:
read_edgelist()函式:用於讀取邊列表檔案,並可透過data引數指定邊屬性。data引數:一個包含元組的列表,用於定義邊屬性的名稱和型別。G.edges(data=True):遍歷所有邊並傳回包含邊屬性的資料。edge_color引數:在draw_networkx()中使用邊的顏色屬性進行視覺化。
鄰接列表格式
鄰接列表是一種更簡潔的表示網路的方式,其中每行第一個節點與後續節點之間存在邊。以下是一個鄰接列表範例:
Winegroom Uptown Strawshop
Uptown Strawshop Amazelake Winegroom
Strawshop Winegroom
Province Strawshop
使用 read_adjlist() 可以輕鬆將鄰接列表轉換為 NetworkX 圖物件:
G = nx.read_adjlist(data_dir / 'example.adjlist')
內容解密:
read_adjlist()函式:讀取鄰接列表檔案並建立圖物件。- 簡潔性:鄰接列表適合表示稠密網路,但無法直接攜帶邊屬性。
GEXF 格式與節點屬性
GEXF 是一種根據 XML 的格式,支援節點和邊的屬性,非常適合複雜網路的表示。要將節點屬性寫入 GEXF 檔案,可以先為節點新增屬性,例如縮寫(abbreviation):
for v in G.nodes:
G.nodes[v]['abbreviation'] = v[0]
然後使用 write_gexf() 將圖物件匯出為 GEXF 檔案:
nx.write_gexf(G, sys.stdout)
輸出結果如下所示,這是一種結構化的表示方式,能夠完整保留節點和邊的屬性:
<?xml version='1.0' encoding='utf-8'?>
<gexf version="1.2" xmlns="http://www.gexf.net/1.2draft">
<!-- 省略部分內容 -->
<nodes>
<node id="Winegroom" label="Winegroom">
<attvalues>
<attvalue for="0" value="W" />
</attvalues>
</node>
<!-- 其他節點 -->
</nodes>
</gexf>
內容解密:
write_gexf()函式:將 NetworkX 圖物件匯出為 GEXF 格式。- 節點屬性:透過為節點新增自定義屬性(如縮寫),豐富網路資料。
- GEXF 結構:採用 XML 結構,能夠清晰地表示節點、邊及其屬性。
此圖示說明瞭不同網路資料格式之間的比較:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 網路資料格式與屬性處理技術
package "網路架構" {
package "應用層" {
component [HTTP/HTTPS] as http
component [WebSocket] as ws
component [gRPC] as grpc
}
package "傳輸層" {
component [TCP] as tcp
component [UDP] as udp
component [TLS/SSL] as tls
}
package "網路層" {
component [IP] as ip
component [ICMP] as icmp
component [路由協議] as routing
}
package "鏈路層" {
component [Ethernet] as eth
component [WiFi] as wifi
component [ARP] as arp
}
}
http --> tcp
ws --> tcp
grpc --> tcp
tcp --> tls : 加密
tls --> ip
udp --> ip
ip --> routing
routing --> eth
routing --> wifi
eth --> arp
@enduml
此圖示內容解說:
- 邊列表:適用於需要攜帶豐富邊屬性的場景。
- 鄰接列表:適合表示稠密網路,簡潔高效。
- GEXF 格式:能夠完整儲存節點和邊的多種屬性,適用於複雜網路。
從資料到網路:探討網路格式與建構方法
在上一章中,我們探討瞭如何使用 NetworkX 來處理和分析網路資料。本章將進一步探討不同的網路格式,以及如何從原始資料構建網路。
網路格式的多樣性
在處理網路資料時,我們經常需要處理不同的檔案格式。NetworkX 支援多種格式,包括 GEXF、GDF、GraphML 和 JSON 等。這些格式各有其特點和適用場景。
GEXF 格式
GEXF(Graph Exchange XML Format)是一種根據 XML 的圖形交換格式。它支援節點和邊的屬性,並且可以包含層次結構。以下是一個 GEXF 檔案的範例:
<gexf xmlns="http://www.gexf.net/1.2draft" version="1.2">
<graph mode="static" defaultedgetype="undirected">
<nodes>
<node id="Winegroom" label="Winegroom">
<attvalues>
<attvalue for="0" value="W" />
</attvalues>
</node>
...
</nodes>
<edges>
<edge id="0" source="Winegroom" target="Uptown" weight="1.0">
<attvalues>
<attvalue for="1" value="red" />
</attvalues>
</edge>
...
</edges>
</graph>
</gexf>
JSON 格式
JSON(JavaScript Object Notation)是一種輕量級的資料交換格式。它易於閱讀和編寫,並且可以被多種程式語言支援。以下是一個 JSON 檔案的範例:
{
"directed": false,
"graph": {},
"links": [
{"color": "red", "source": "Winegroom", "target": "Uptown", "weight": 1.0},
...
],
"multigraph": false,
"nodes": [
{"abbreviation": "W", "id": "Winegroom"},
...
]
}
從原始資料構建網路
有時候,我們需要從原始資料構建網路。這可以透過逐步新增節點和邊來實作。以下是一個使用 Python 和 NetworkX 建構詞共現網路的範例:
詞共現網路
詞共現網路是一種用於理解檔案中詞彙之間關係的網路。在這種網路中,節點代表詞彙,而邊的權重代表它們在同一句中出現的次數。
import re
import networkx as nx
def co_occurrence_network(text):
# 建立一個新的網路
G = nx.Graph()
# 將文字分割成句子並迭代處理
sentences = text.split('.')
for s in sentences:
# 移除標點符號並轉換為小寫
clean = re.sub('[^\w\n ]+', '', s).lower()
clean = re.sub('_+', '', clean).strip()
# 建立詞彙清單
words = re.split('\s+', clean)
# 為每個詞彙建立節點和邊
for v in words:
try:
G.nodes[v]['count'] += 1
except KeyError:
G.add_node(v)
G.nodes[v]['count'] = 1
for w in words:
if v == w or v in ['the', 'of', 'and'] or w in ['the', 'of', 'and']:
continue
if len(v) == 0 or len(w) == 0:
continue
try:
G.edges[v, w]['count'] += 1
except KeyError:
G.add_edge(v, w, count=1)
return G
# 讀取文字資料
with open('frankenstein.txt') as f:
text = f.read()
# 建立詞共現網路
G = co_occurrence_network(text)
# 對邊進行排序
pairs = sorted(G.edges(data=True), key=lambda e: e[2]['count'], reverse=True)
print(pairs[0:10])
內容解密:
co_occurrence_network函式:該函式接受一個文字字串作為輸入,並傳回一個詞共現網路。- 文字預處理:函式首先將文字分割成句子,然後移除標點符號並轉換為小寫。
- 建立節點和邊:函式為每個詞彙建立節點,並為每對在同一句中出現的詞彙建立邊。
- 排序邊:最後,函式對邊進行排序,以找出最常共現的詞彙對。
從資料到網路:關聯網路的建立與分析
在前一章節中,我們探討瞭如何將資料轉化為網路並進行基本分析。本章節將深入介紹關聯網路(Affiliation Networks)的概念及其在NetworkX中的實作。
節點與關聯
許多現實世界的關係涉及多於兩個節點。例如,在電影演員的關係網路中,一部電影通常有多位演員,而一位演員也可以出演多部電影。這種多對多的關係可以透過引入第二種型別的節點來表示,從而形成關聯網路。
六度分隔理論與關聯網路
「六度分隔理論」的一個著名應用是「Kevin Bacon的遊戲」。在這個遊戲中,目標是找到任意演員與Kevin Bacon之間的聯絡。例如,Jon Hamm透過與Rose Byrne共同出演《伴娘》等電影,而Rose Byrne又與Kevin Bacon共同出演《X戰警:第一戰》,從而建立了與Kevin Bacon的聯絡。
這種遊戲根據一個網路,其中節點代表演員,邊代表兩位演員共同出演的電影。然而,這種表示方法存在侷限性:每部電影需要多條邊來表示其所有演員之間的關係,如果一部電影只有一位演員,則不會在網路中出現。為瞭解決這個問題,可以引入一個新的網路結構——關聯網路,其中包含兩種型別的節點:演員和電影。每條邊連線一位演員和一部他參與的電影。
關聯網路的定義
正式來說,關聯網路(或稱二部網路)是一種具有兩種型別節點的網路,並且只允許不同型別節點之間的連線。這與標準的單一型別網路不同,後者只包含一種節點。兩種型別的節點可以被稱為「頂部」和「底部」或「左側」和「右側」,但這些只是用於區分的稱呼。
NetworkX中的關聯網路
NetworkX提供了對關聯網路的支援,使得建立、檢測、操作和視覺化這種網路變得容易。
import networkx as nx
import matplotlib.pyplot as plt
# 建立一個空的關聯網路
G = nx.Graph()
# 新增兩種型別的節點:演員和電影
actors = ['Jon Hamm', 'Rose Byrne', 'Kevin Bacon']
movies = ['Bridesmaids', 'X-Men: First Class']
G.add_nodes_from(actors, bipartite=0) # 演員
G.add_nodes_from(movies, bipartite=1) # 電影
# 新增邊:演員與電影之間的關係
G.add_edge('Jon Hamm', 'Bridesmaids')
G.add_edge('Rose Byrne', 'Bridesmaids')
G.add_edge('Rose Byrne', 'X-Men: First Class')
G.add_edge('Kevin Bacon', 'X-Men: First Class')
# 檢查網路是否是二部的
print(nx.is_bipartite(G))
# 視覺化關聯網路
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, nodelist=actors, node_color='lightblue')
nx.draw_networkx_nodes(G, pos, nodelist=movies, node_color='lightgreen')
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos)
plt.show()
內容解密:
- 建立關聯網路:首先,我們建立一個空圖
G,然後分別新增兩種型別的節點(演員和電影),並使用bipartite屬性區分它們。 - 新增邊:根據實際關係,在不同型別的節點之間新增邊。
- 檢查二部性:使用
nx.is_bipartite(G)檢查圖是否是二部的,以確保其結構正確。 - 視覺化:透過區分不同型別的節點顏色來視覺化關聯網路,使其更容易理解。
投影
在某些情況下,我們可能希望將關聯網路轉換為單一型別的網路,這可以透過投影實作。投影是將關聯網路中的一種型別的節點轉換為新的網路,其中兩個節點之間的邊根據它們在原網路中分享的鄰居數量。
投影示例
# 取得演員的投影
actors_projection = nx.bipartite.projected_graph(G, actors)
# 視覺化演員投影網路
pos = nx.spring_layout(actors_projection)
nx.draw_networkx_nodes(actors_projection, pos)
nx.draw_networkx_edges(actors_projection, pos)
nx.draw_networkx_labels(actors_projection, pos)
plt.show()
內容解密:
- 投影操作:使用
nx.bipartite.projected_graph函式對指定的節點型別(例如演員)進行投影,生成新的單一型別網路。 - 視覺化投影網路:展示投影後的網路,有助於分析不同演員之間的合作關係。