您當前的位置:首頁 > 體育

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

作者:由 NebulaGraph 發表于 體育時間:2020-09-01

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

在上一篇[1]中,我們透過 NetworkX 和 Gephi 展示了<權力的遊戲>中的人物關係。在本篇中,我們將展示如何透過 NetworkX 訪問圖資料庫 Nebula Graph。

NetworkX

NetworkX [2] 是一個用 Python 語言開發的圖論與複雜網路建模工具,內建了大量常用的圖與複雜網路分析演算法,可以方便地進行復雜網路資料分析、模擬建模等工作,功能豐富,簡單易用。

在 NetworkX 中,圖是由頂點、邊和可選的屬性構成的資料結構。頂點表示資料,邊是由兩個頂點唯一確定的,表示兩個頂點之間的關係。頂點和邊也可以擁有更多的屬性,以儲存更多的資訊。

NetworkX 支援 4 種類型的圖:

Graph:無向圖

DiGraph: 有向圖

MultiGraph: 多重無向圖

MultiDiGraph: 多重有向圖

在 NetworkX 中建立一個無向圖:

import

networkx

as

nx

G

=

nx

Graph

()

新增頂點:

G

add_node

1

G

add_nodes_from

([

2

3

4

])

G

add_node

2

name

=

‘Tom’

age

=

23

新增邊:

G

add_edge

2

3

G

add_edges_from

([(

1

2

),(

1

3

)])

g

add_edge

1

2

start_year

=

1996

end_year

=

2019

在上一篇文章(一)中,我們已經演示了 NetworkX 的 Girvan-Newman 社群發現演算法。

圖資料庫 Nebula Graph

NetworkX 通常使用本地檔案作為資料來源,這在靜態網路研究的時候沒什麼問題,但如果圖網路經常會發生變化——例如某些中心節點已經不存在(Fig。1)或者引入了重要的網路拓撲變化(Fig。2)——每次生成全新的靜態檔案再載入分析就有些麻煩,最好整個變化過程可以持久化在一個數據庫中,並且可以實時地直接從資料庫中載入子圖或者全圖做分析。本文選用 Nebula Graph [3]作為儲存圖資料的圖資料庫。

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

Fig。 1

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

Fig。 2

Nebula Graph 提供了兩種方式來獲取圖結構:

編寫一個查詢語句,拉取一個子圖;

全量掃描底層儲存,獲取一個完整的全圖。

第一種方式適合在一個大規模的圖網路中透過精細的過濾和剪枝條件來獲取符合需求的若干個點和邊。第二種方式更適合於全圖的分析,這通常是在專案前期對全圖進行一些啟發式探索,當有進一步認知後再用第一種方式做精細的剪枝分析。

分析完 Nebula Graph 兩種獲取圖結構方式後,下面來檢視 Nebula Graph 的 Python 客戶端程式碼,nebula-python/nebula/ngStorage/StorageClient。py 與 nebula-python/nebula/ngMeta/MetaClient。py 就是和底層儲存互動的 API, 裡面有掃描點、掃描邊、讀取一堆屬性等等一系列豐富的介面。

下面兩個介面可以用來讀取所有的點、邊資料:

def

scan_vertex

self

space

return_cols

all_cols

limit

start_time

end_time

def

scan_edge

self

space

return_cols

all_cols

limit

start_time

end_time

1) 初始化一個客戶端,和一個 scan_edge_processor。scan_edge_processor 用來對讀出來的邊資料進行解碼:

meta_client

=

MetaClient

([(

‘192。168。8。16’

45500

)])

meta_client

connect

()

storage_client

=

StorageClient

meta_client

scan_edge_processor

=

ScanEdgeProcessor

meta_client

2) 初始化 scan_edge 介面的各項引數:

space_name

=

‘nba’

# 要讀取的圖空間名稱

return_cols

=

{}

# 要返回的邊(或點)及其屬性列

return_cols

‘serve’

=

‘start_year’

‘end_year’

return_cols

‘follow’

=

‘degree’

allCols

=

False

# 是否返回所有屬性列,當該值為 False 時,僅返回在 returnCols 裡指定的屬性列,當為 True 時,返回所有屬性列

limit

=

100

# 最多返回的資料條數

start_time

=

0

end_time

=

sys

maxsize

3) 呼叫 scan_part_edge 介面,該介面會返回一個 scan_edge_response 物件的迭代器:

scan_edge_response_iterator

=

storage_client

scan_edge

space_name

return_cols

all_cols

limit

start_time

end_time

4) 不斷讀取該迭代器所指向的 scan_edge_response 物件中的資料,直到讀取完所有資料:

while

scan_edge_response_iterator

has_next

():

scan_edge_response

=

scan_edge_response_iterator

next

()

if

scan_edge_response

is

None

print

“Error occurs while scaning edge”

break

process_edge

space

scan_edge_response

其中,process_edge 是自定義的一個處理讀出來邊資料的函式,該函式可以先使用 scan_edge_processor 對 scan_edge_response 中的資料進行解碼,解碼後的資料可以直接打印出來,也可以做一些簡單處理,另作他用,比如:將這些資料讀入計算框架 NetworkX 裡。

5) 處理資料。在這裡我們將讀出來的所有邊都新增到 NetworkX 中的圖G 裡:

def

process_edge

space

scan_edge_response

):

result

=

scan_edge_processor

process

space

scan_edge_response

# Get the corresponding rows by edge_name

for

edge_name

edge_rows

in

result

rows

items

():

for

row

in

edge_rows

srcId

=

row

default_properties

0

get_value

()

dstId

=

row

default_properties

2

get_value

()

print

%d

->

%d

%

srcId

dstId

))

props

=

{}

for

prop

in

row

properties

prop_name

=

prop

get_name

()

prop_value

=

prop

get_value

()

props

prop_name

=

prop_value

G

add_edges_from

([(

srcId

dstId

props

)])

# 新增邊到 NetworkX 中的圖G

讀取頂點資料的方法和上面的流程類似。

此外,對於分散式的一些圖計算框架[4]來說,Nebula Graph 還提供了根據分片 (partition) 併發地批次讀取儲存的功能,這會在之後的文章中演示。

在 NetworkX 中進行圖分析

當我們把所有點和邊資料都按照上述流程讀入 NetworkX 後,我們還可以做一些基本的圖分析和圖計算:

1) 繪製圖:

nx

draw

G

with_labels

=

True

font_weight

=

‘bold’

import

matplotlib。pyplot

as

plt

plt

show

()

plt

savefig

‘。/test。png’

繪製出來的圖:

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

2) 打印出圖中的所有點和邊:

print

‘nodes: ’

list

G

nodes

))

print

‘edges: ’

list

G

edges

))

輸出的結果:

nodes

109

119

129

139

149

209

219

229

108

118

128

138

148

208

218

228

107

117

127

137

147

207

217

227

106

116

126

136

146

206

216

226

101

111

121

131

141

201

211

221

100

110

120

130

140

150

200

210

220

102

112

122

132

142

202

212

222

103

113

123

133

143

203

213

223

104

114

124

134

144

204

214

224

105

115

125

135

145

205

215

225

edges

[(

109

100

),

109

125

),

109

204

),

109

219

),

109

222

),

119

200

),

119

205

),

119

113

),

129

116

),

129

121

),

129

128

),

129

216

),

129

221

),

129

229

),

129

137

),

139

138

),

139

212

),

139

218

),

149

130

),

149

219

),

209

123

),

219

130

),

219

112

),

219

104

),

229

147

),

229

116

),

229

141

),

229

144

),

108

100

),

108

101

),

108

204

),

108

206

),

108

214

),

108

215

),

108

222

),

118

120

),

118

131

),

118

205

),

118

113

),

128

116

),

128

121

),

128

201

),

128

202

),

128

205

),

128

223

),

138

115

),

138

204

),

138

210

),

138

212

),

138

221

),

138

225

),

148

127

),

148

136

),

148

137

),

148

214

),

148

223

),

148

227

),

148

213

),

208

127

),

208

103

),

208

104

),

208

124

),

218

127

),

218

110

),

218

103

),

218

104

),

218

114

),

218

105

),

228

146

),

228

145

),

107

100

),

107

204

),

107

217

),

107

224

),

117

200

),

117

136

),

117

142

),

127

114

),

127

212

),

127

213

),

127

214

),

127

222

),

127

226

),

127

227

),

137

136

),

137

213

),

137

150

),

147

136

),

147

214

),

147

223

),

207

121

),

207

140

),

207

122

),

207

134

),

217

126

),

217

141

),

217

124

),

217

144

),

106

204

),

106

212

),

106

113

),

116

141

),

116

126

),

116

210

),

116

216

),

116

121

),

116

113

),

116

105

),

126

216

),

136

210

),

136

213

),

136

214

),

146

202

),

146

210

),

146

215

),

146

222

),

146

226

),

206

123

),

216

144

),

216

105

),

226

140

),

226

112

),

226

114

),

226

144

),

101

100

),

101

102

),

101

125

),

101

204

),

101

215

),

101

113

),

101

104

),

111

200

),

111

204

),

111

215

),

111

220

),

121

202

),

121

215

),

121

113

),

121

134

),

131

205

),

131

220

),

141

124

),

141

205

),

141

225

),

201

145

),

211

124

),

221

104

),

221

124

),

100

125

),

100

204

),

100

102

),

100

113

),

100

104

),

100

144

),

100

105

),

110

204

),

110

220

),

120

150

),

120

202

),

120

205

),

120

113

),

140

114

),

140

214

),

140

224

),

150

143

),

150

213

),

200

142

),

200

104

),

200

145

),

210

124

),

210

144

),

210

115

),

210

145

),

102

203

),

102

204

),

102

103

),

102

135

),

112

204

),

122

213

),

122

223

),

132

225

),

202

133

),

202

114

),

212

103

),

222

104

),

103

204

),

103

114

),

113

104

),

113

105

),

113

125

),

113

204

),

133

114

),

133

144

),

143

213

),

143

223

),

203

135

),

213

124

),

213

145

),

104

105

),

104

204

),

104

215

),

114

115

),

114

204

),

134

224

),

144

145

),

144

214

),

204

105

),

204

125

)]

3) 常見的,可以計算兩個點之間的最短路徑:

p1

=

nx

shortest_path

G

source

=

114

target

=

211

print

‘頂點 114 到頂點 211 的最短路徑: ’

p1

輸出的結果:

頂點

114

到頂點

211

的最短路徑

114

127

208

124

211

4) 也計算圖中每個點的 PageRank 值,來看各自的影響力:

print

nx

pagerank

G

))

輸出的結果:

{109: 0。011507076520104863, 119: 0。007835838669313514, 129: 0。015304593799331218, 139: 0。007772926737873626, 149: 0。0073896601012629825, 209: 0。0065558926178649985, 219: 0。014100908598251508, 229: 0。011454115940170253, 108: 0。01645334474680034, 118: 0。01010598371500564, 128: 0。01594717876199238, 138: 0。01671097227127263, 148: 0。015898676579503977, 208: 0。009437234075904938, 218: 0。0153795416919104, 228: 0。005900393773635255, 107: 0。009745182763645681, 117: 0。008716335675518244, 127: 0。021565565312365507, 137: 0。011642680498867146, 147: 0。009721031073465738, 207: 0。01040504770909835, 217: 0。012054472529765329, 227: 0。005615576255373405, 106: 0。007371191843767635, 116: 0。020955704443679106, 126: 0。007589432032220849, 136: 0。015987209357117116, 146: 0。013922108926721374, 206: 0。008554794629575304, 216: 0。011219193251536395, 226: 0。013613173390725904, 101: 0。016680863106330837, 111: 0。010121524312495604, 121: 0。017545503989576015, 131: 0。008531567756846938, 141: 0。014598319866130227, 201: 0。0058643663430632525, 211: 0。003936285336338021, 221: 0。009587911774927793, 100: 0。02243017302167168, 110: 0。007928429795381916, 120: 0。011875669801396205, 130: 0。0073896601012629825, 140: 0。01205992633948699, 150: 0。010045605782606326, 200: 0。015289870550944322, 210: 0。017716629501785937, 220: 0。008666577509181518, 102: 0。014865431161046641, 112: 0。007931095811770324, 122: 0。008087439927630492, 132: 0。004659566123187912, 142: 0。006487446038191551, 202: 0。013579313206377282, 212: 0。01190888044566142, 222: 0。011376739416933006, 103: 0。013438110749144392, 113: 0。02458154500563397, 123: 0。01104978432213578, 133: 0。00743370900670294, 143: 0。008011123394996112, 203: 0。006883198710237787, 213: 0。020392557117890422, 223: 0。012345866520333572, 104: 0。024902235588979776, 114: 0。019369722463816744, 124: 0。017165705442951484, 134: 0。008284361176173354, 144: 0。019363506469972095, 204: 0。03507634139024834, 214: 0。015500649025348538, 224: 0。008320315540621754, 105: 0。01439975542831122, 115: 0。007592722237637133, 125: 0。010808523955754608, 135: 0。006883198710237788, 145: 0。014654713389044883, 205: 0。014660118545887803, 215: 0。01337467974572934, 225: 0。009909720748343093}

此外,也可以和上一篇中一樣,接入Gephi [5]來得到更好的圖視覺化效果。

本文的程式碼可以參見[6]。

Reference

[1]

https://

nebula-graph。com。cn/pos

ts/game-of-thrones-relationship-networkx-gephi-nebula-graph/

[2]

https://

networkx。github。io/

[3] https://github。com/vesoft-inc/nebula

[4]

https://

spark。apache。org/graphx

/

[5]

https://

gephi。org/

[6]

https://

github。com/vesoft-inc/n

ebula-python/pull/31

喜歡這篇文章?來來來,給我們的 GitHub 點個 star 表鼓勵啦~~ ‍♂️ ‍♀️ [手動跪謝]

交流圖資料庫技術?交個朋友,Nebula Graph 官方小助手微信:NebulaGraphbot 拉你進交流群~~

作者有話說:Hi,我是王傑,是圖資料 Nebula Graph 研發工程師,希望本次的經驗分享能給大家帶來幫助,如有不當之處也希望能幫忙糾正,謝謝~

標簽: edge  204  scan  114  100