網路分析中,資料格式的選擇至關重要。GEXF 根據 XML,支援節點和邊的屬性,適用於動態網路;JSON 輕量級且易於解析,方便與 JavaScript 相關應用整合。詞共現網路則能展現文字中詞彙間的關聯性,透過 Python 和 NetworkX,可以有效地建構此類別網路。程式碼流程包含文字預處理,去除標點符號和停用詞,接著建立節點和邊,並根據詞彙共同出現的次數更新邊的權重,最後能得到一個表示詞彙關聯性的網路圖。
從資料到網路:探討網路格式與建構方法
在網路分析的世界中,資料的表示和處理是至關重要的環節。NetworkX 提供了多種方法來讀取和寫入網路資料,包括 GEXF、GraphML 和 JSON 等格式。本篇文章將探討這些格式的特點和應用場景,並介紹如何使用程式碼建立一個詞共現網路。
網路資料格式的選擇
在處理網路資料時,選擇合適的資料格式非常重要。不同的格式有不同的優缺點,瞭解這些特點可以幫助我們更好地處理和分析網路資料。
GEXF 格式
GEXF(Graph Exchange XML Format)是一種根據 XML 的圖形交換格式。它支援節點和邊的屬性,並且可以表示動態網路。以下是一個 GEXF 格式的範例:
<gexf>
<graph>
<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)是一種輕量級的資料交換格式。它易於閱讀和編寫,同時也易於機器解析和生成。NetworkX 支援將網路資料匯出為 JSON 格式,這對於與 JavaScript 或 ECMAScript 相關的應用非常方便。
{
"directed": false,
"graph": {},
"links": [
{"color": "red", "source": "Winegroom", "target": "Uptown", "weight": 1.0},
{"color": "orange", "source": "Winegroom", "target": "Strawshop", "weight": 5.0},
<!-- 其他邊 -->
],
"multigraph": false,
"nodes": [
{"abbreviation": "W", "id": "Winegroom"},
{"abbreviation": "U", "id": "Uptown"},
<!-- 其他節點 -->
]
}
程式碼實作:建立詞共現網路
詞共現網路是一種用於理解特設定檔案中詞彙之間關係的網路。在這種網路中,節點代表詞彙,而邊的權重則代表這些詞彙在同一檔案中共同出現的次數。
詞共現網路的建構步驟
- 文字預處理:將文字分割成句子,並移除標點符號和停用詞(如冠詞、代詞等)。
- 建立網路:為每個句子中的詞彙建立節點,並為共同出現的詞彙之間建立邊。
- 更新邊的權重:根據詞彙共同出現的次數更新邊的權重。
以下是一個 Python 函式,用於建立詞共現網路:
import re
import networkx as nx
def co_occurrence_network(text):
G = nx.Graph()
sentences = text.split('.')
stop_words = set(['the', 'of', 'and']) # 停用詞列表
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 stop_words or w in stop_words:
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),這是一種特殊的網路結構,用於表示多對多的關係。
節點與關聯
在許多現實世界的場景中,關係往往涉及兩個以上的節點。例如,在電影演員的關係網路中,演員與電影之間的關係就不能簡單地用單一型別的節點來表示。為瞭解決這個問題,我們引入了關聯網路的概念。
關聯網路的定義
關聯網路,也稱為二分網路(Bipartite Network),是一種具有兩種型別節點的網路,並且只允許不同型別節點之間的連線。在演員-電影網路中,兩種型別的節點分別代表演員和電影,邊則代表演員參與了某部電影的拍攝。
為何需要關聯網路
傳統的單一模式網路(Single-mode Networks)只能表示兩個節點之間的關係,無法直接表示多對多的關係。例如,在演員-電影關係中,如果僅使用演員節點,則每部電影需要多條邊來連線參與該電影的所有演員,這不僅冗餘,而且無法直接表示電影與演員之間的隸屬關係。
在 NetworkX 中處理關聯網路
NetworkX 提供了豐富的功能來建立、操作和視覺化關聯網路。以下是一些關鍵步驟:
建立關聯網路
import networkx as nx
# 建立一個空的關聯網路
G = nx.Graph()
# 新增兩種型別的節點:演員和電影
actors = ['Actor1', 'Actor2', 'Actor3']
movies = ['Movie1', 'Movie2']
G.add_nodes_from(actors, bipartite=0) # 演員節點
G.add_nodes_from(movies, bipartite=1) # 電影節點
# 新增邊,表示演員參與電影
G.add_edge('Actor1', 'Movie1')
G.add_edge('Actor2', 'Movie1')
G.add_edge('Actor3', 'Movie2')
#### 內容解密:
此段程式碼展示瞭如何建立一個關聯網路。首先,我們匯入 `networkx` 函式庫並建立一個空圖 `G`。然後,我們定義了兩種型別的節點:演員和電影,並使用 `add_nodes_from` 方法將它們新增到圖中,同時透過 `bipartite` 引數區分節點型別。最後,我們使用 `add_edge` 方法新增邊,表示演員與電影之間的關係。
投影(Projections)
在某些情況下,我們可能需要將關聯網路轉換為單一模式網路,這可以透過投影來實作。投影是指根據關聯網路中的一種節點型別,構建出該型別節點之間的連線關係。
# 取得演員的投影網路
actors_nodes = [node for node in G.nodes if G.nodes[node]['bipartite'] == 0]
G_actor_projected = nx.bipartite.projected_graph(G, actors_nodes)
#### 內容解密:
此程式碼首先篩選出所有演員節點,然後使用 `projected_graph` 方法生成演員的投影網路。在這個投影網路中,兩個演員之間有邊相連當且僅當他們在原關聯網路中共同參與了一部或多部電影。
視覺化關聯網路
視覺化是理解網路結構的重要手段。對於關聯網路,我們可以分別視覺化原始的二分網路或其投影。
import matplotlib.pyplot as plt
# 視覺化原始關聯網路
pos = nx.spring_layout(G)
nx.draw_networkx(G, pos, with_labels=True)
plt.show()
#### 內容解密:
此程式碼使用 `spring_layout` 佈局演算法對關聯網路進行佈局,並使用 `draw_networkx` 方法繪製網路,最後顯示圖形。透過這種方式,可以直觀地觀察到演員與電影之間的關係。
參考資料
- Shelley, Mary Wollstonecraft. (1818). Frankenstein; or The Modern Prometheus.
- Urbina, Illinois: Project Gutenberg. Retrieved February 21, 2016, from www.gutenberg.org/ebooks/19033.
圖表翻譯:
此圖示顯示了演員與電影之間的二分網路結構,清楚地展示了多對多的關係。透過這樣的視覺化,可以更好地理解複雜的關係結構。
從關係到網路:關聯網路的探討
在複雜網路的研究中,關聯網路(Affiliation Networks)是一種特殊的網路結構,用於描述兩類別不同實體之間的關聯關係。這種網路在社交網路分析、生物網路研究以及資訊傳播分析等領域具有廣泛的應用。
關聯網路的基本概念
關聯網路由兩類別節點組成,通常代表不同型別的實體,例如音樂家和歌曲、作者和論文、演員和電影等。在這類別網路中,節點之間的連線僅在不同型別的節點之間發生,即音樂家只與歌曲相連,歌曲只與音樂家相連。
常見的關聯網路示例
- 電子郵件網路:發件人/收件人與郵件之間的關係
- 共同作者網路:作者與論文之間的關係
- 公司董事會網路:董事成員與公司董事會之間的關係
- 立法網路:代表與法案之間的關係
- 書籍翻譯網路:語言與書籍之間的關係
- 媒體報導網路:國家/主題與媒體通路之間的關係
- 線上標籤網路:標籤與帖子之間的關係
- 自然語言處理:單詞與檔案之間的關係
- 翻唱歌曲網路:音樂家與歌曲之間的關係
- 代謝網路:化學物質與反應之間的關係
- 美食網路:食材與食譜之間的關係
使用 NetworkX 表示關聯網路
在 NetworkX 中,關聯網路可以使用 Graph 和 DiGraph 類別來表示。為了區分不同型別的節點,可以使用容器(如列表或集合)來儲存特定型別的節點 ID,或者將節點型別作為節點屬性儲存。
# 匯入必要的模組
from networkx.algorithms import bipartite
from networkx import NetworkXError
import networkx as nx
# 載入 Zachary 空手道俱樂部網路
G = nx.karate_club_graph()
try:
# 查詢並列印節點集合
left, right = bipartite.sets(G)
print("左側節點\n", left)
print("\n右側節點\n", right)
except NetworkXError as e:
# 不是關聯網路
print(e)
將 Zachary 空手道俱樂部網路轉換為關聯網路
# 建立新的圖 B
B = nx.Graph()
# 新增邊緣,將原始節點和邊緣作為新節點
B.add_edges_from([(v, (v, w)) for v, w in G.edges])
B.add_edges_from([(w, (v, w)) for v, w in G.edges])
try:
# 查詢並列印節點集合
left, right = bipartite.sets(B)
print("左側節點\n", left)
print("\n右側節點\n", right)
except NetworkXError as e:
# 不是關聯網路
print(e)
# #### 內容解密:
# 這段程式碼首先匯入必要的模組,然後載入 Zachary 空手道俱樂部網路。接著,它嘗試將該網路轉換為關聯網路,並列印預出轉換後的節點集合。
# - `bipartite.sets(G)` 用於檢查圖 G 是否為關聯網路,並傳回兩個節點集合。
# - `NetworkXError` 例外處理用於捕捉圖 G 不是關聯網路的情況。
# - `B.add_edges_from([(v, (v, w)) for v, w in G.edges])` 和 `B.add_edges_from([(w, (v, w)) for v, w in G.edges])` 將原始圖 G 的邊緣轉換為新圖 B 中的節點,並建立新的邊緣連線。
### 傳粉者網路示例
傳粉者網路是關聯網路的一個實際應用示例,用於描述動物物種與植物物種之間的傳粉關係。下面是載入並處理傳粉者網路資料的程式碼示例:
```python
# 建立資料目錄路徑
from pathlib import Path
data_dir = Path('.') / 'data'
# 初始化圖 B
B = nx.Graph()
with open(data_dir / 'bartomeus2008' / 'Bartomeus_Ntw_nceas.txt') as f:
# 跳過標題行
next(f)
for row in f:
# 將行分解為單元格
cells = row.strip().split('\t')
# 取得植物物種和傳粉者物種
plant = cells[4].replace('_', '\n')
pollinator = cells[8].replace('_', '\n')
# 新增邊緣
B.add_edge(pollinator, plant)
# 設定節點型別
B.nodes[pollinator]["bipartite"] = 0
B.nodes[plant]["bipartite"] = 1
# 只考慮連線的物種
B = B.subgraph(list(nx.connected_components(B))[0])
# #### 內容解密:
# 這段程式碼用於載入並處理傳粉者網路資料。
# - `with open(data_dir / 'bartomeus2008' / 'Bartomeus_Ntw_nceas.txt') as f:` 開啟包含傳粉者網路資料的檔案。
# - `next(f)` 跳過檔案的標題行。
# - `cells = row.strip().split('\t')` 將每一行資料分解為單元格。
# - `plant = cells[4].replace('_', '\n')` 和 `pollinator = cells[8].replace('_', '\n')` 取得植物物種和傳粉者物種的名稱,並將下劃線替換為換行符。
# - `B.add_edge(pollinator, plant)` 在傳粉者和植物之間新增邊緣。
# - `B.nodes[pollinator]["bipartite"] = 0` 和 `B.nodes[plant]["bipartite"] = 1` 設定節點的型別屬性。
視覺化傳粉者網路
# 建立圖形
import matplotlib.pyplot as plt
plt.figure(figsize=(30,30))
# 計算佈局
pos = nx.spring_layout(B, k=0.9)
# 使用不同的形狀和顏色繪製植物/傳粉者
nx.draw_networkx_edges(B, pos, width=3, alpha=0.2)
nx.draw_networkx_nodes(B, pos, nodelist=[v for v in B.nodes if B.nodes[v]["bipartite"] == 1], node_color="#bfbf7f",
node_shape="h", node_size=3000)
nx.draw_networkx_nodes(B, pos, nodelist=[v for v in B.nodes if B.nodes[v]["bipartite"] == 0], node_color="#9f9fff",
node_size=3000)
nx.draw_networkx_labels(B, pos)
# #### 內容解密:
# 這段程式碼用於視覺化傳粉者網路。
# - `pos = nx.spring_layout(B, k=0.9)` 使用 spring layout 演算法計算節點的位置。
# - `nx.draw_networkx_edges(B, pos, width=3, alpha=0.2)` 繪製邊緣。
# - `nx.draw_networkx_nodes(B, pos, nodelist=[v for v in B.nodes if B.nodes[v]["bipartite"] == 1], node_color="#bfbf7f", node_shape="h", node_size=3000)` 繪製植物物種的節點,使用六邊形和特定的顏色。
# - `nx.draw_networkx_nodes(B, pos, nodelist=[v for v in B.nodes if B.nodes[v]["bipartite"] == 0], node_color="#9f9fff", node_size=3000)` 繪製傳粉者物種的節點,使用圓形和特定的顏色。