摘自:http://www.toutiao.com/a6305624170701783298/
其中的分析和可視化是用Gephi做的,Gephi是非常流行的圖分析工具氓涣。但作者覺得使用Neo4j來實(shí)現(xiàn)更有趣。
導(dǎo)入原始數(shù)據(jù)到Neo4j
原始數(shù)據(jù)可從網(wǎng)絡(luò)上下載昌妹,格式如下:
Source,Target,Weight
Aemon,Grenn,5
Aemon,Samwell,31
Aerys,Jaime,18 ...
上面是人物關(guān)系的之鄰接表以及關(guān)系權(quán)重寝衫。作者使用簡單的數(shù)據(jù)模型:
(:Character {name})-[:INTERACTS]->(:Character {name})
帶有標(biāo)簽Character的節(jié)點(diǎn)代表小說中的角色,用單向關(guān)系類型INTERACTS代表小說中的角色有過接觸啸澡。節(jié)點(diǎn)屬性會(huì)存儲(chǔ)角色的名字name,兩角色間接觸的次數(shù)作為關(guān)系的屬性:權(quán)重(weight)。
首先創(chuàng)建節(jié)點(diǎn)c铲咨,并做唯一限制性約束汹胃,c.name唯一,保證schema的完整性:
CREATE CONSTRAINT ON (c:Character) ASSERT c.name IS UNIQUE;
一旦約束創(chuàng)建即相應(yīng)的創(chuàng)建索引皮服,這將有助于通過角色的名字查詢的性能楞艾。作者使用Neo4j的Cypher(Cypher是一種聲明式圖查詢語言,能表達(dá)高效查詢和更新圖數(shù)據(jù)庫)LOAD CSV語句導(dǎo)入數(shù)據(jù):
LOAD CSV WITH HEADERS FROM "https://www.macalester.edu/~abeverid/data/stormofswords.csv" AS rowMERGE (src:Character {name: row.Source})MERGE (tgt:Character {name: row.Target})MERGE (src)-[r:INTERACTS]->(tgt)SET r.weight = toInt(row.Weight)
這樣得到一個(gè)簡單的數(shù)據(jù)模型:
CALL apoc.meta.graph
圖1 :《權(quán)力的游戲》模型的圖龄广。Character角色節(jié)點(diǎn)由INTERACTS關(guān)系聯(lián)結(jié)
我們能可視化整個(gè)圖形硫眯,但是這并不能給我們很多信息,比如哪些是最重要的人物择同,以及他們相互接觸的信息:
MATCH p=(:Character)-[:INTERACTS]-(:Character) RETURN p
圖2
人物網(wǎng)絡(luò)分析
作者使用Neo4j的圖查詢語言Cypher來做《權(quán)力的游戲》圖分析两入,應(yīng)用到了網(wǎng)絡(luò)分析的一些工具,具體見《網(wǎng)絡(luò)奠衔,人群和市場:關(guān)于高度連接的世界》谆刨。
人物數(shù)量
萬事以簡單開始塘娶。先看看上圖上由有多少人物:
MATCH (c:Character) RETURN count(c)
count(c)
107
概要統(tǒng)計(jì)
統(tǒng)計(jì)每個(gè)角色接觸的其它角色的數(shù)目:
MATCH (c:Character)-[:INTERACTS]->() WITH c, count(*) AS num RETURN min(num) AS min, max(num) AS max, avg(num) AS avg_characters, stdev(num) AS stdev
圖(網(wǎng)絡(luò))的直徑
網(wǎng)絡(luò)的直徑或者測(cè)底線或者最長最短路徑:
// Find maximum diameter of network // maximum shortest path between two nodes
MATCH (a:Character), (b:Character) WHERE id(a) > id(b) MATCH p=shortestPath((a)-[:INTERACTS*]-(b)) RETURN length(p) AS len, extract(x IN nodes(p) | x.name) AS path ORDER BY len DESC LIMIT 4
我們能看到網(wǎng)絡(luò)中有許多長度為6的路徑。
最短路徑
作者使用Cypher 的shortestPath函數(shù)找到圖中任意兩個(gè)角色之間的最短路徑痊夭。讓我們找出凱特琳·史塔克(Catelyn Stark )和卓戈·卡奧(Kahl Drogo)之間的最短路徑:
// Shortest path from Catelyn Stark to Khal Drogo
MATCH (catelyn:Character {name: "Catelyn"}), (drogo:Character {name: "Drogo"}) MATCH p=shortestPath((catelyn)-[INTERACTS*]-(drogo)) RETURN p
圖3
所有最短路徑
聯(lián)結(jié)凱特琳·史塔克(Catelyn Stark )和卓戈·卡奧(Kahl Drogo)之間的最短路徑可能還有其它路徑刁岸,我們可以使用Cypher的allShortestPaths函數(shù)來查找:
// All shortest paths from Catelyn Stark to Khal Drogo
MATCH (catelyn:Character {name: "Catelyn"}), (drogo:Character {name: "Drogo"}) MATCH p=allShortestPaths((catelyn)-[INTERACTS*]-(drogo)) RETURN p
圖4
關(guān)鍵節(jié)點(diǎn)
在網(wǎng)絡(luò)中,如果一個(gè)節(jié)點(diǎn)位于其它兩個(gè)節(jié)點(diǎn)所有的最短路徑上她我,即稱為關(guān)鍵節(jié)點(diǎn)虹曙。下面我們找出網(wǎng)絡(luò)中所有的關(guān)鍵節(jié)點(diǎn):
// Find all pivotal nodes in network
MATCH (a:Character), (b:Character) MATCH p=allShortestPaths((a)-[:INTERACTS*]-(b)) WITH collect(p) AS paths, a, b MATCH (c:Character) WHERE all(x IN paths WHERE c IN nodes(x)) AND NOT c IN [a,b] RETURN a.name, b.name, c.name AS PivotalNode SKIP 490 LIMIT 10
從結(jié)果表格中我們可以看出有趣的結(jié)果:羅柏·史塔克(Robb)是卓戈·卡奧(Drogo)和拉姆塞·波頓(Ramsay)的關(guān)鍵節(jié)點(diǎn)。這意味著番舆,所有聯(lián)結(jié)卓戈·卡奧(Drogo)和拉姆塞·波頓(Ramsay)的最短路徑都要經(jīng)過羅柏·史塔克(Robb)酝碳。我們可以通過可視化卓戈·卡奧(Drogo)和拉姆塞·波頓(Ramsay)之間的所有最短路徑來驗(yàn)證:
MATCH (a:Character {name: "Drogo"}), (b:Character {name: "Ramsay"}) MATCH p=allShortestPaths((a)-[:INTERACTS*]-(b)) RETURN p
圖5