1. 程式人生 > 實用技巧 >用 NetworkX + Gephi + Nebula Graph 分析<權力的遊戲>人物關係(上篇)

用 NetworkX + Gephi + Nebula Graph 分析<權力的遊戲>人物關係(上篇)

我們都知道《權利的遊戲》在全世界都很多忠實的粉絲,除去你永遠不知道劇情下一秒誰會掛這種意外“驚喜”,當中複雜交錯的人物關係也是它火爆的原因之一,而本文介紹如何通過 NetworkX 訪問開源的分散式圖資料庫 Nebula Graph,並藉助視覺化工具—— Gephi 來視覺化分析《權力的遊戲》中的複雜的人物圖譜關係。

資料集

本文的資料集來源:冰與火之歌第一卷(至第五卷)[1]

  • 人物集 (點集):書中每個角色建模為一個點,點只有一個屬性:姓名
  • 關係集(邊集):如果兩個角色在書中發生過直接或間接的互動,則有一條邊;邊只有一個屬性:權重,權重的大小代表互動的強弱。

這樣的點集和邊集構成一個圖網路,這個網路儲存在圖資料庫

Nebula Graph [2]中。

社區劃分——Girvan-Newman 演算法

我們使用 NetworkX [3] 內建的社群發現演算法 Girvan-Newman 來為我們的圖網路劃分社群。

以下為「社群發現演算法 Girvan-Newman」解釋:

網路圖中,連線較為緊密的部分可以被看成一個社群。每個社群內部節點之間有較為緊密的連線,而在兩個社群間連線則較為稀疏。社群發現就是找到給定網路圖所包含的一個個社群的過程。

Girvan-Newman 演算法即是一種基於介數的社群發現演算法,其基本思想是根據邊介數中心性(edge betweenness)從大到小的順序不斷地將邊從網路中移除直到整個網路分解為各個社群。因此,Girvan-Newman 演算法實際上是一種分裂方法。

Girvan-Newman 演算法的基本流程如下:
(1)計算網路中所有邊的邊介數;
(2)找到邊介數最高的邊並將它從網路中移除;
(3)重複步驟 2,直到每個節點成為一個獨立的社群為止,即網路中沒有邊存在。

概念解釋完畢,下面來實操下。

  1. 使用 Girvan-Newman 演算法劃分社群。NetworkX 示例程式碼如下
comp = networkx.algorithms.community.girvan_newman(G)
k = 7
limited = itertools.takewhile(lambda c: len(c) <= k, comp)
communities = list(limited)[-1]
  1. 為圖中每個點新增一個 community 屬性,該屬性值記錄該點所在的社群編號
community_dict = {}
community_num = 0
for community in communities:
    for character in community:
        community_dict[character] = community_num
        community_num += 1
        nx.set_node_attributes(G, community_dict, 'community')

節點樣式——Betweenness Centrality 演算法

下面我們來調整下節點大小及節點上標註的角色姓名大小,我們使用 NetworkX 的 Betweenness Centrality 演算法來決定節點大小及節點上標註的角色姓名的大小。

圖中各個節點的重要性可以通過節點的中心性(Centrality)來衡量。在不同的網路中往往採用了不同的中心性定義來描述網路中節點的重要性。Betweenness Centrality 根據有多少最短路徑經過該節點,來判斷一個節點的重要性。

  1. 計算每個節點的介數中心性的值
betweenness_dict = nx.betweenness_centrality(G) # Run betweenness centrality
  1. 為圖中每個點再新增一個 betweenness 屬性
nx.set_node_attributes(G, betweenness_dict, 'betweenness')

邊的粗細

邊的粗細直接由邊的權重屬性來決定。

通過上面的處理,現在,我們的節點擁有 name、community、betweenness 三個屬性,邊只有一個權重 weight 屬性。

下面顯示一下:

import matplotlib.pyplot as plt
color = 0
color_map = ['red', 'blue', 'yellow', 'purple', 'black', 'green', 'pink']
for community in communities:
    nx.draw(G, pos = nx.spring_layout(G, iterations=200), nodelist = community, node_size = 100, node_color = color_map[color])
    color += 1
plt.savefig('./game.png')

emmm,有點醜…

雖然 NetworkX 本身有不少視覺化功能,但 Gephi [4] 的互動和視覺化效果更好。

接入視覺化工具 Gephi

現在將上面的 NetworkX 資料匯出為 game.gephi 檔案,並匯入 Gephi。

nx.write_gexf(G, 'game.gexf')

Gephi 視覺化效果展示

在 Gephi 中開啟剛才匯出的 game.gephi 檔案,然後微調 Gephi 中的各項引數,就以得到一張滿意的視覺化:

  1. 將佈局設定為 Force Atlas, 斥力強度改為為 500.0, 勾選上 由尺寸調整 選項可以儘量避免節點重疊:

Force Atlas 為力引導佈局,力引導佈局方法能夠產生相當優美的網路佈局,並充分展現網路的整體結構及其自同構特徵。力引導佈局即模仿物理世界的引力和斥力,自動佈局直到力平衡。

  1. 給劃分好的各個社群網路畫上不同的顏色:

在外觀-節點-顏色-Partition 中選擇 community(這裡的 community 就是我們剛才為每個點新增的社群編號屬性)

  1. 決定節點及節點上標註的角色姓名的大小:

在外觀-節點-大小-Ranking 中選擇 betweenness(這裡的 betweenness 就是我們剛才為每個點新增的 betweenness 屬性)

  1. 邊的粗細由邊的權重屬性來決定:

在外觀-邊-大小-Ranking 中選擇邊的權重

  1. 匯出圖片再加個頭像效果

大功告成,一張權力遊戲的關係譜圖上線