NetworkX 是一個功能強大的 Python 函式庫,專門用於建立、操作和研究複雜網路的結構、動態和功能。本文將探討如何使用 NetworkX 進行加權網路視覺化和有向圖分析,並解析不同圖形型別及其應用場景。首先,我們會示範如何利用 spring_layout() 函式根據邊權重調整節點位置,並使用 draw_networkx() 函式根據邊權重繪製不同顏色的邊,以清晰地呈現網路結構。接著,將介紹如何使用 NetworkX 處理有向圖(DiGraph),包含讀取 GEXF 格式資料、繪製有向圖、區分前驅和後繼節點,以及將有向圖轉換為無向圖等操作。除了基本圖形操作,本文還會探討 NetworkX 支援的不同圖形型別,例如無向圖、有向圖、多圖和多有向圖,並說明它們在不同網路分析場景下的應用。最後,我們將深入研究 NetworkX 如何處理不同格式的網路資料,例如邊列表、加權邊列表、鄰接列表和 GEXF 格式,並示範如何讀取和設定節點屬性和邊屬性,以便進行更深入的網路分析和視覺化。
加權網路視覺化與有向圖分析
在網路分析中,節點之間的連線強度往往具有重要意義。以Zachary的空手道俱樂部網路為例,透過引入邊權重(edge weight)來表示成員間的聯絡緊密程度,能夠更準確地呈現網路結構。
加權網路視覺化
在NetworkX中,可以透過spring_layout()函式的weight引數來實作根據邊權重的佈局調整。以下程式碼展示瞭如何視覺化加權網路:
weighted_pos = nx.spring_layout(G, pos=karate_pos, k=0.3, weight="weight")
nx.draw_networkx(
G, weighted_pos, width=8, node_color=node_color,
edge_color=edge_weights, edge_cmap=plt.cm.Blues,
edge_vmin=0, edge_vmax=6)
nx.draw_networkx_edges(
G, weighted_pos, edgelist=internal, edge_color="gray")
nx.draw_networkx_edges(
G, weighted_pos, edgelist=external, edge_color="gray", style="dashed")
內容解密:
spring_layout()函式根據邊權重調整節點位置,使強連線的節點更為接近。draw_networkx()函式根據邊權重為邊著色,使用Blues色彩對映表,使權重較高的邊呈現較深的藍色。- 透過兩次呼叫
draw_networkx_edges(),分別繪製內部和外部邊,內部邊使用實線,外部邊使用虛線,以區分不同型別的連線。
有向圖(DiGraph)分析
在許多實際網路中,節點之間的關係具有方向性,例如員工與上司之間的關係。NetworkX中的DiGraph類別支援有向圖的操作。
有向圖的基本操作
G = nx.read_gexf("data/knecht2008/klas12b-net-1.gexf")
student_pos = nx.spring_layout(G, k=1.5)
nx.draw_networkx(G, pos, arrowsize=20)
內容解密:
read_gexf()函式讀取GEFX格式的網路資料。spring_layout()函式計算節點位置。draw_networkx()函式繪製有向圖,並透過arrowsize引數調整箭頭大小,使方向性更為明顯。
有向圖中的鄰居節點
在有向圖中,一個節點的鄰居可以分為前驅(predecessor)和後繼(successor)。
list(G.neighbors(0))
list(G.successors(0))
list(G.predecessors(0))
內容解密:
neighbors()方法傳回節點的後繼節點,等同於successors()方法。predecessors()方法傳回節點的前驅節點。- 一個節點可能同時是另一個節點的前驅和後繼。
有向圖轉無向圖
有時需要將有向圖轉換為無向圖進行分析,DiGraph類別提供了to_undirected()方法。
G_either = G.to_undirected()
G_both = G.to_undirected(reciprocal=True)
內容解密:
to_undirected()方法預設建立一個無向圖,只要原有向圖中任一方向存在邊,就會在無向圖中建立一條無向邊。- 設定
reciprocal=True時,只有當原有向圖中雙向都存在邊時,才會在無向圖中建立一條無向邊。
從資料到網路:NetworkX 的應用
在利用 NetworkX 分析系統時,首先需要將該系統建模為網路,然後在 NetworkX 中表示為物件。本章節將闡述建立資料網路表示的基本過程。第一部分涵蓋在腦海中進行的過程:將資料建模為網路。其餘部分則透過程式碼展示如何實作:使用兩種不同的方法從資料建立 NetworkX 圖形。
將資料建模為網路
在將資料表示為網路時,需要做出許多決定。不同型別的網路有助於理解不同型別的資料,並提出不同型別的問題。本文將更仔細地探討一些重要的考慮因素。
定義節點和邊緣
在從資料建立網路時,最重要的問題之一是節點和邊緣究竟應該代表什麼。通常,即使對於相同的資料集,也有許多可能性。任何特定的選擇都會聚焦於資料的某些方面,可能會丟棄其他方面。網路從根本上講是關於關係和連線,因此定義節點和邊緣的一種方法是思考你感興趣的關係型別。一些可能性包括:
- 社會關係,如友誼、戀愛關係,甚至是競爭對手關係
- 流動,如資訊、人、資金、流體或能量
- 影響力,如科學參照、軟體依賴或蛋白質互動作用
- 連線,如網路電腦之間的連線、骨骼中的骨骼、鄰國或鐵路線路
- 互動,如捕食者與獵物的關係或國際條約
- 文字中共現的詞語
一旦你知道你想了解什麼型別的關係,節點的選擇應該是顯而易見的:社交網路中的人、蛋白質互動作用中的蛋白質、國際條約中的國家等。同樣,關係的性質通常會建議使用什麼型別的網路。流動具有方向性,建議使用有向網路。鐵路線允許雙向行駛,建議使用無向網路。如果你對非常具有傳染性的疾病是否能在兩個人之間傳播感興趣,你可能只需要一個未加權的網路。但是,如果感染通常需要多次接觸,你可能需要一個加權網路來跟蹤兩個人互動的次數。當然,總是可以從相同的資料集建立多個網路,以研究多個問題。
網路檔案:將網路儲存到檔案中
NetworkX 支援多種標準的網路格式,可以將建立的網路儲存到檔案中,以便於後續使用或與其他工具分享。
從程式碼建立網路
對於更複雜的資料,可以透過程式碼逐步新增節點和邊緣,從頭開始建立網路。這種方法提供了更大的靈活性,可以根據特定的需求自定義網路建立的過程。
NetworkX 中的不同圖形型別
有向與無向圖
NetworkX 提供了 Graph 類別用於無向網路,以及 DiGraph 類別用於有向網路。這兩種類別分別適用於不同型別的關係和連線。
多圖與多有向圖
在某些情況下,兩個節點之間可能存在多條邊緣,例如柯尼斯堡七橋問題中的橋樑。在這種情況下,MultiGraph 和 MultiDiGraph 類別就派上了用場,它們允許在相同的兩個端點之間新增任意數量的邊緣。
# 柯尼斯堡七橋
G = nx.MultiGraph()
G.add_edges_from([
("北岸", "克奈珀霍夫島", {"橋樑": "克拉默橋"}),
("北岸", "克奈珀霍夫島", {"橋樑": "施密德橋"}),
("北岸", "洛姆瑟島", {"橋樑": "霍爾茨橋"}),
("洛姆瑟島", "克奈珀霍夫島", {"橋樑": "大教堂橋"}),
("南岸", "克奈珀霍夫島", {"橋樑": "綠橋"}),
("南岸", "克奈珀霍夫島", {"橋樑": "科特爾橋"}),
("南岸", "洛姆瑟島", {"橋樑": "高橋"})
])
內容解密:
此範例程式碼展示瞭如何使用 MultiGraph 類別來表示柯尼斯堡七橋問題。在這個例子中,我們建立了一個多圖 G,並新增了代表七座橋樑的邊緣,每個邊緣都有一個屬性 橋樑 用於標識橋樑的名稱。這種表示方法允許我們在相同的兩個節點之間新增多條邊緣,從而準確地建模柯尼斯堡七橋問題。
從資料到網路:網路檔案的讀取與寫入
在網路科學的研究中,將資料轉化為網路結構是至關重要的步驟。Wikipedia 的文章之間存在多種關係,例如主題相關性、編輯者之間的合作關係等,這些都可以被建模成不同的網路結構。接下來,我們將探討如何使用 NetworkX 來讀取和寫入網路檔案,並介紹幾種常見的網路檔案格式。
網路檔案的格式
NetworkX 支援多種網路檔案格式,包括鄰接表(Adjacency List)、邊列表(Edge List)、GEXF 和 JSON 等。這些格式各有其特點和適用場景。
邊列表(Edge List)
邊列表是一種簡單且實用的純文字格式。它支援邊屬性,但不支援節點屬性。邊列表的讀取和寫入可以透過 read_edgelist() 和 write_edgelist() 函式來實作。
邊列表檔案的內容
一個邊列表檔案的示例內容如下:
# 示例邊列表網路
# 源 目標
Winegroom Uptown
Winegroom Strawshop
Uptown Strawshop
Uptown Amazelake
Strawshop Province
在這個示例中,每一行代表一條邊,節點 ID 之間用空白字元分隔。以 # 開頭的行被視為註解,會被 NetworkX 忽略。
加權邊列表
邊列表格式也支援加權邊。透過在每行的第三個位置新增權重值,並使用 read_weighted_edgelist() 函式讀取檔案,可以將權重值新增到邊屬性中。
加權邊列表檔案的內容
一個加權邊列表檔案的示例內容如下:
# 示例加權邊列表網路
# 源 目標 權重
Winegroom Uptown 1
Winegroom Strawshop 5
Uptown Strawshop 9
Uptown Amazelake 6
Strawshop Province 3
使用 NetworkX 讀取邊列表檔案
要讀取邊列表檔案,首先需要匯入必要的模組並指定資料目錄:
from pathlib import Path
import networkx as nx
import matplotlib.pyplot as plt
data_dir = Path('.') / 'data'
然後,可以使用 read_edgelist() 函式讀取邊列表檔案並建立一個 Graph 物件:
G = nx.read_edgelist(data_dir / 'example.edgelist')
對於有向網路,可以透過指定 create_using 引數為 nx.DiGraph 來建立一個 DiGraph 物件:
G = nx.read_edgelist(data_dir / 'example.edgelist', create_using=nx.DiGraph)
視覺化網路
讀取網路後,可以使用 draw_networkx() 函式進行視覺化:
pos = nx.spring_layout(G)
nx.draw_networkx(G, pos)
plt.gca().margins(0.15, 0.15)
plt.show()
對於加權網路,可以提取邊權重並根據權重繪製網路:
G = nx.read_weighted_edgelist(data_dir / 'weighted.edgelist')
weights = [d['weight'] for s, t, d in G.edges(data=True)]
# 繪製網路並根據權重設定邊顏色
#### 內容解密:
- 匯入必要的模組:使用
from pathlib import Path和import networkx as nx分別匯入處理路徑和網路分析所需的模組。 - 指定資料目錄:透過
data_dir = Path('.') / 'data'指定存放資料的目錄。 read_edgelist()函式:用於讀取邊列表檔案並建立 Graph 或 DiGraph 物件,取決於是否指定create_using=nx.DiGraph。draw_networkx()函式:用於繪製網路圖,結合spring_layout()可以實作美觀的佈局。- 提取邊權重:透過列表推導式
[d['weight'] for s, t, d in G.edges(data=True)]提取每條邊的權重,用於後續的視覺化或分析。
圖表翻譯:
此圖示展示了一個簡單的有向或無向網路結構,以及如何透過 NetworkX 將其視覺化。節點代表實體(如 Wikipedia 文章或編輯者),邊代表它們之間的關係(如連結或合作)。透過調整引數(如是否為有向圖、是否包含權重),可以滿足不同的分析需求。
從資料到網路:深入理解網路資料格式與屬性
在網路分析與視覺化的過程中,資料的表示方式對於後續的處理和分析至關重要。NetworkX 提供了多種讀取和寫入網路資料的格式,包括邊列表(edge list)、鄰接列表(adjacency list)以及 GEXF 格式等。本章節將探討這些格式的特點、應用場景以及如何使用 NetworkX 進行操作。
邊列表格式及其屬性
邊列表是一種常見的網路表示方法,每一行代表一條邊,通常包含源節點、目標節點以及可選的邊屬性。例如,在一個模擬的地鐵網路中,我們可以使用邊列表來表示站點之間的連線關係,並附上權重和其他屬性,如顏色。
# 示例邊列表網路
# 源 目標 資料1 資料2 ...
Winegroom Uptown 1 red
Winegroom Strawshop 5 orange
Uptown Strawshop 9 blue
Uptown Amazelake 6 red
Strawshop Province 3 orange
內容解密:
- 每行代表一條邊,第一列是源節點,第二列是目標節點,後續列可表示邊的屬性,如權重和顏色。
- 在這個例子中,
Winegroom和Uptown之間有一條權重為 1 且顏色為紅色的邊。 - 這種格式允許我們指定邊的屬性,但不直接支援節點屬性的表示。
讀取邊列表及其屬性
NetworkX 提供了 read_edgelist() 和 read_weighted_edgelist() 函式來讀取邊列表。透過傳遞 data 引數,我們可以指定如何解析邊屬性。
# 讀取邊列表
G = nx.read_edgelist(
data_dir / 'attributes.edgelist',
data=[('weight', float), ('color', str)])
# 提取顏色屬性
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引數指定邊屬性的解析方式。- 在這個例子中,我們定義了兩個屬性:
weight和color,分別對應浮點數和字串型別。 - 將提取的顏色屬性傳遞給
draw_networkx()的edge_color引數,實作了根據顏色屬性繪製網路。
鄰接列表格式
鄰接列表是一種簡潔的網路表示方法,每一行代表一個節點及其鄰居節點。這種格式不直接支援邊屬性的表示,但在某些場景下非常方便。
# 示例鄰接列表網路
# 源 目標1 目標2 ...
Winegroom Uptown Strawshop
Uptown Strawshop Amazelake Winegroom
Strawshop Winegroom
Province Strawshop
內容解密:
- 每行第一個節點與後續節點之間存在邊的關係。
- 這種格式簡潔,但無法直接表示邊屬性。
GEXF 格式與節點屬性
GEXF 是一種根據 XML 的網路表示格式,支援節點和邊的多種屬性。NetworkX 可以輕鬆讀寫 GEXF 檔案,使其成為跨工具合作的首選格式之一。
# 新增節點屬性
for v in G.nodes:
G.nodes[v]['abbreviation'] = v[0]
# 匯出為 GEXF 格式
import sys
nx.write_gexf(G, sys.stdout)
內容解密:
- 為每個節點增加了一個名為
abbreviation的屬性,其值為節點名稱的第一個字元。 - 使用
write_gexf()將網路匯出為 GEXF 格式,並輸出到標準輸出。
此圖示
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title NetworkX 加權網路視覺化與圖分析
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。其中,邊列表支援邊屬性的表示;鄰接列表以簡潔著稱,但不直接支援邊屬性;GEXF則全面支援節點和邊的多種屬性。透過這樣的分類別,可以根據具體需求選擇最合適的資料表示方法,以最佳化後續的網路分析和視覺化工作。