我的導師沈浩教授對復雜網(wǎng)絡深有研究做葵,他的博士論文研究的就是關(guān)系視角下的傳播網(wǎng)絡酗洒。本科時候我在聽課過程中對網(wǎng)絡科學的一些術(shù)語有了基本的認知窗骑,也產(chǎn)生興趣但惶。下面就是自己的一些感知吧耳鸯!21世紀的科學研究不再是原子式的,而是in vivo的膀曾,是在系統(tǒng)論指導下開展的整合研究县爬。對任何系統(tǒng)的考察都應該追求整合,而非割裂添谊,系統(tǒng)由集合财喳、結(jié)構(gòu)、功能組成斩狱,頗有結(jié)構(gòu)功能主義的色彩耳高。進一步而言,一些系統(tǒng)的基礎(chǔ)結(jié)構(gòu)其實都是由組成要素共同協(xié)調(diào)所踊、自我運轉(zhuǎn)形成的網(wǎng)絡泌枪,目的在于發(fā)揮一定的功能,一些系統(tǒng)的核心結(jié)構(gòu)都是邏輯網(wǎng)絡秕岛,而一些復雜系統(tǒng)的結(jié)構(gòu)都是復雜網(wǎng)絡工闺,人類社會就是一個復雜社會,人的態(tài)度瓣蛀、行為其實受很多方面的影響陆蟆,這也順帶解釋了為什么社會科學研究中決定系數(shù)如此低的原因,而且人本身就是復雜的惋增。社會網(wǎng)絡研究如果脫離純粹的關(guān)系討論叠殷,結(jié)合一下節(jié)點的屬性和邊(關(guān)系)的變化,那么社會網(wǎng)絡研究實際上就是對復雜系統(tǒng)進行的研究诈皿。
復雜網(wǎng)絡研究就是對系統(tǒng)中各元素間的相互關(guān)聯(lián)作用及所形成的拓撲結(jié)構(gòu)進行的研究林束,結(jié)構(gòu)復雜性像棘、節(jié)點復雜性、相互影響復雜性等等一系列復雜性都是復雜網(wǎng)絡研究的核心壶冒,也是網(wǎng)絡科學研究的價值所在缕题。
所以我要從基礎(chǔ)開始,先從社會科學領(lǐng)域的基礎(chǔ)網(wǎng)絡研究入手胖腾,逐步關(guān)注更高難度烟零、更復雜的網(wǎng)絡科學研究。有兩本書是目前在看的:
劉軍《整體網(wǎng)分析:UCINET軟件實用指南》
羅家德《社會網(wǎng)分析講義》
在學習的一門MOOC是
北大社會學系邱澤奇教授咸作、北大計算機學院李曉明教授合授的《人群與網(wǎng)絡》(內(nèi)容豐富锨阿,啟發(fā)思維,真的是開啟了新世界的大門)
在學習的分析工具除了劉軍老師書中教授的UCINET軟件记罚,就是現(xiàn)在在玩的Python中的NetworkX包墅诡。
鉆研網(wǎng)絡研究的人,軟件固然好用桐智,但是為了研究各種問題末早,離不開寫代碼,更需要掌握幾個包说庭,我選擇的第一個包是NetworkX然磷。我直接根據(jù)文檔學習的,主要看examples口渔。
NetworkX是一個Python包,用來創(chuàng)建穿撮、研究網(wǎng)絡結(jié)構(gòu)及結(jié)構(gòu)動態(tài)演化缺脉。其中包括一些基本的圖算法集成、可以直接和數(shù)據(jù)文件交互悦穿,結(jié)合igraph攻礼、Matplotlib一起使用效果會更好。
我的電腦是Mac OS Sierra 10.12.6栗柒,因為在用GraphLab礁扮,所以安裝的是Python 2.7,不過也同時安裝了Python 3.6瞬沦,但是我更喜歡在Python 2.7中進行網(wǎng)絡研究太伊。
基本的操作包括:
# 導入包,初始化一個網(wǎng)絡圖
import networkx as nx
G = nx.Graph()
網(wǎng)絡圖就是節(jié)點與邊的集合逛钻,nx中的節(jié)點可以是任何哈希對象僚焦,包括字符串、圖片曙痘、XML對象等芳悲。
簡單的操作就是手動添加節(jié)點與邊(節(jié)點之間的關(guān)系)立肘。
節(jié)點
# 添加單個節(jié)點
G.add_node(1)
# 添加多個節(jié)點,需要用列表
G.add_nodes_from([2, 3])
需要查看一下現(xiàn)在的網(wǎng)絡圖長什么樣
# 導入matplotlib名扛,我在ipynb里寫代碼谅年,所以用了inline
% matplotlib inline
% pylab inline
# 繪圖
nx.draw(G, with_labels=True)
結(jié)果是有三個加了標簽的小紅點
G = nx.Graph()
# path_graph:返回一系列順序節(jié)點,如果是整數(shù)n肮韧,那么就是0-n融蹂,也可以是包含節(jié)點信息的可迭代對象
H = nx.path_graph(10)
G.add_nodes_from(H)
nx.draw(G, with_labels=True)
網(wǎng)絡圖中的節(jié)點呈圓環(huán)排列,以上做法是把H的節(jié)點搶來放到G中惹苗,同樣地殿较,還可以把整個H作為G的一個節(jié)點,即一張包含了網(wǎng)絡子圖的網(wǎng)絡圖
G.add_node(H)
nx.draw(G, with_labels=True)
結(jié)果是生成的網(wǎng)絡圖中有一個節(jié)點寫著path_graph(10)
桩蓉,也就是所謂的graph of graph.
邊
可以一次只加一條邊
# 現(xiàn)在1淋纲、2節(jié)點上加一條邊
G.add_edge(1, 2)
e = (2, 3)
# 如果是要寫成元組形式,那么導入邊時需要用*拆解
G.add_edge(*e)
nx.draw(G, with_labels=True)
可以同時加入一系列邊
G.add_edges_from([(1, 3), (3, 5)])
nx.draw(G, with_labels=True)
移除所有的節(jié)點與邊
# 移除所有的節(jié)點和邊
G.clear()
nx.draw(G, with_labels=True)
會生成一個空圖院究。
節(jié)點與邊
只要指定邊的關(guān)系洽瞬,就會自動生成邊關(guān)系里的節(jié)點,無需再次添加節(jié)點
G.add_edges_from([(1, 2), (1, 3)])
# G.add_node(1)
# G.add_edge(1, 2)
G.add_node('spam')
nx.draw(G, with_labels=True)
但是添加節(jié)點也不都是一樣的业汰,add_node
和add_nodes_from
差別很大
G.add_nodes_from('spam')
# 會添加四個節(jié)點:'s', 'p', 'a', 'm'
G.add_edge(3, 'm')
nx.draw(G, with_labels=True)
# 查看節(jié)點數(shù)量和邊的數(shù)量
print G.number_of_nodes()
# 8
print G.number_of_edges()
# 3
對于節(jié)點伙窃、邊的基礎(chǔ)統(tǒng)計,最常見的是:G.nodes
, G.edges
, G.adj
, G.degree
print G.nodes()
# ['a', 1, 2, 3, 'spam', 'm', 'p', 's']
print G.edges()
# [(1, 2), (1, 3), (3, 'm')]
print G.adj
# 展示出與某個節(jié)點存在直接聯(lián)系的節(jié)點集合
# {'a': {}, 1: {2: {}, 3: {}}, 2: {1: {}}, 3: {1: {}, 'm': {}}, 'spam': {}, 'm': {3: {}}, 'p': {}, 's': {}}
print G.degree()
# 度:與某個節(jié)點有聯(lián)系的節(jié)點數(shù)量
# {'a': 0, 1: 2, 2: 1, 3: 2, 'spam': 0, 'm': 1, 'p': 0, 's': 0}
還可以批量匯報基礎(chǔ)統(tǒng)計量样漆,類似于[nodeA, nodeB]
的查詢方式叫做nbunch
为障,nbunch
可以是None(返回所有節(jié)點/邊的信息),可以是單個節(jié)點放祟,也可以是包含多個節(jié)點的可迭代對象鳍怨。
print G.edges([2, 'm'])
# [(2, 1), ('m', 3)]
print G.degree([2, 3, 4])
# {2: 1, 3: 2}
# 因為沒有節(jié)點4,所以返回結(jié)果中略過4
除了添加節(jié)點和邊跪妥,也可以移除節(jié)點和邊鞋喇。
G.remove_node(2)
G.remove_nodes_from('spam')
nx.draw(G, with_labels=True)
原有的圖瞬間少了很多節(jié)點,而且刪除節(jié)點眉撵,對應的邊也會消失侦香。
G.remove_edge(1, 3)
G.add_edge(1, "spam")
nx.draw(G, with_labels=True)
現(xiàn)在的網(wǎng)絡都是無向的,當然還可以指定網(wǎng)絡圖的形式纽疟,比如構(gòu)建有向網(wǎng)絡罐韩。
G.add_edge(1, 3)
H = nx.DiGraph(G)
print H.edges()
# [(1, 3), (1, 'spam'), (3, 1), ('spam', 1)]
nx.draw(H, with_labels=True)
edge_list = [(1, 2), (1, 3), (2, 3)]
H = nx.DiGraph(edge_list)
print H.edges()
# [(1, 2), (1, 3), (2, 3)]
nx.draw(H, with_labels=True)
今天就寫到這里,還有別的事情要做……