淺談社會網絡分析(Social Network Analysis)

早前試過用Steemit的數據玩過文本分析,現在就打算用數據試一下別的。想了想就覺得社會網絡分析應該會挺有趣,所以先開個帖子跟大家說一下這是一種什麼分析,還有怎樣用Python去實現這個東西。

什麼是社會網絡分析


社會網絡就是把有關係的人連起來而成的一個組織,大概就像下面圖示這樣:

(圖片來源: https://goo.gl/LkkGCp)

那麼社會網絡分析就是運用圖論(Graph theory)從這些連結去研究整個結構,比如看看一個群體能分成多少個圈子(Clustering)、誰是每一個圈裏的軸心個體(Key Person)或是把每個人之間的關係緊密程度圖像化等等。

舉一個實際例子,社會網絡分析對於Facebook就有很大作用,比如它可以用於向用戶建議一些他們可能會認識的朋友。但像這種比較深入的分析會需要用到一些數學模型,今天就淺談一點,說說怎樣把數據圖像化以了解一個群體的結構。

在說明怎樣用Python寫編碼之前,我們先來看看一些例子:

用一個比較簡單的情況,比如有18個人(A – R),有以下的關係:

A-B, A-C, A-D, A-E, A-F, A-G, A-H,
H-I, H-J, H-K, H-M, H-N, H-O,
P-Q, P-R, P-H, B-C, D-F, B-G

那麼把它們畫出來就是這個樣子 (圖1):
P2.png

這裏大概就能看到三個群組,分別以H、A跟P為軸心。在這裏我們是沒有考慮人與人之間的親密度,假設我們已用某種方法把人跟人之間的親密度量化,就能製作一個加權的版本。

假設關係不變,且除了H跟P比較疏離、A跟H比較親近之外其他人的親密度是一樣的,那麼結果如下 (圖2):
P3.png
上圖所用的加權為:

個體1個體2加權(Weight)個體1個體2加權(Weight)
AH3HK1
PH0.5HM1
AB1HN1
AC1HO1
AD1PQ1
AE1PR1
AF1BC1
AG1DF1
HI1BG1
HJ1

這裏我用了線的粗幼來區分親密度,所以你能看到P跟H中間的線明顯是比其他線要幼很多的,而A跟H中間的線明顯比較粗。除了線的粗幼,還可以用顏色、長短這些來反映關係的程度,但在這就不一一做出來了,讓大家自己發掘一下。

以上看到的都是沒有方向關係(Undirected Graph),但有些社會網絡中的關係可以是單向或是雙向的,例如在Facebook上誰向誰發出交友邀請(單向)、誰向誰點讚(單向/雙向)等等,這時候我們需要製作有向圖(Directed Graph / Digraph) (圖3):

P4.png

如上圖,比較粗的一邊就等同箭頭,所以舉A跟H作例子,方向是從A指向H的。有向圖就能讓你發現原來H是一個接受者,假如圖中的方向是發出交友邀請的方向,那麼就等於H是一個不會主動發交友邀請的人,都是其他人主動加他為朋友的。

怎樣用Python去實現結果

我用的是Python裡面一個叫Networkx的library,其實用的編碼都很簡單 ( //後的是我的備註):

import networkx as nx
G=nx.Graph() // 定義G為一個網絡圖

G.add_edge('A', 'B') // 在G裡面把A跟B兩個個體連上
G.add_edge('A', 'C') // 這裡我就只保留了其中兩句,要製作上面的網絡你需要自己繼續連上其他個體

pos=nx.spring_layout(G) // 定義pos為G的佈圖 (layout),除了spring以外還有其他如circular, random, spectral等等的佈圖可以選擇

nx.draw_networkx_nodes(G,pos,node_size=1500, alpha=0.5) // 把G裡面的個體(node)畫出來,alpha是透明度

nx.draw_networkx_edges(G,pos,alpha=0.5, edge_color ='b') // 把G裡面個體間的線(edge)畫出來

nx.draw_networkx_labels(G,pos,font_size=13,font_color='w') // 把G裡面個體的名稱顯示出來

如果需要加入個體間的關係程度作加權的話 (如圖2),就需要改以下編碼:

  • G.add_edge裡面的函數中加上weight:

G.add_edge('A', 'H', weight = 3)
G.add_edge('A', 'B', weight = 1) // 同樣地,這裡只用了其中2句作例子

  • 然後加上一句代碼:

edgewidth = [d['weight'] for (u,v,d) in G.edges(data=True)]

  • 再在nx.draw_networkx_edges裡面的函數中加上width = edgewidth

nx.draw_networkx_edges(G,pos,alpha=0.5, edge_color ='b', width=edgewidth)

如果需要製作有向圖 (如圖3),則把

G=nx.graph()

改成

G=nx.Digraph()

就可以了,Digraph就是Directed graph的意思。
大家可以試試動手做,也不妨用Steemit的數據玩一下~ 過一兩天我會用Steemit的數據跑一下結果,再跟大家分享 :)


其實單純用Python去做的話結果圖是不太美觀的,而且當數據量巨大的時候結果會很難看,所以我個人會用Python把結果導出成graphml的格式,再用Gephi(一個專門把網絡圖像化的程式)去處理,下圖就是一個用Gephi製作的網絡圖的例子,但這個如果大家有興趣的話我晚一點再談吧。

P5.jpg
(圖片來源: https://goo.gl/Qur35C)

謝謝收看~ 希望大家發現數據分析其實也可以很有趣啦


歡迎Follow我 @rayccy :)

H2
H3
H4
3 columns
2 columns
1 column
10 Comments