网络科学研究 001
我的导师沈浩教授对复杂网络深有研究,他的博士论文研究的就是关系视角下的传播网络。本科时候我在听课过程中对网络科学的一些术语有了基本的认知,也产生兴趣。下面就是自己的一些感知吧!21世纪的科学研究不再是原子式的,而是in vivo的,是在系统论指导下开展的整合研究。对任何系统的考察都应该追求整合,而非割裂,系统由集合、结构、功能组成,颇有结构功能主义的色彩。进一步而言,一些系统的基础结构其实都是由组成要素共同协调、自我运转形成的网络,目的在于发挥一定的功能,一些系统的核心结构都是逻辑网络,而一些复杂系统的结构都是复杂网络,人类社会就是一个复杂社会,人的态度、行为其实受很多方面的影响,这也顺带解释了为什么社会科学研究中决定系数如此低的原因,而且人本身就是复杂的。社会网络研究如果脱离纯粹的关系讨论,结合一下节点的属性和边(关系)的变化,那么社会网络研究实际上就是对复杂系统进行的研究。
复杂网络研究就是对系统中各元素间的相互关联作用及所形成的拓扑结构进行的研究,结构复杂性、节点复杂性、相互影响复杂性等等一系列复杂性都是复杂网络研究的核心,也是网络科学研究的价值所在。
所以我要从基础开始,先从社会科学领域的基础网络研究入手,逐步关注更高难度、更复杂的网络科学研究。有两本书是目前在看的:
刘军《整体网分析:UCINET软件实用指南》
罗家德《社会网分析讲义》
在学习的一门MOOC是
北大社会学系邱泽奇教授、北大计算机学院李晓明教授合授的《人群与网络》(内容丰富,启发思维,真的是开启了新世界的大门)
在学习的分析工具除了刘军老师书中教授的UCINET软件,就是现在在玩的Python中的NetworkX包。
钻研网络研究的人,软件固然好用,但是为了研究各种问题,离不开写代码,更需要掌握几个包,我选择的第一个包是NetworkX。我直接根据文档学习的,主要看examples。
NetworkX是一个Python包,用来创建、研究网络结构及结构动态演化。其中包括一些基本的图算法集成、可以直接和数据文件交互,结合igraph、Matplotlib一起使用效果会更好。
我的电脑是Mac OS Sierra 10.12.6,因为在用GraphLab,所以安装的是Python 2.7,不过也同时安装了Python 3.6,但是我更喜欢在Python 2.7中进行网络研究。
基本的操作包括:
# 导入包,初始化一个网络图
import networkx as nx
G = nx.Graph()
网络图就是节点与边的集合,nx中的节点可以是任何哈希对象,包括字符串、图片、XML对象等。
简单的操作就是手动添加节点与边(节点之间的关系)。
节点
# 添加单个节点
G.add_node(1)
# 添加多个节点,需要用列表
G.add_nodes_from([2, 3])
需要查看一下现在的网络图长什么样
# 导入matplotlib,我在ipynb里写代码,所以用了inline
% matplotlib inline
% pylab inline
# 绘图
nx.draw(G, with_labels=True)
结果是有三个加了标签的小红点
img 1G = nx.Graph()
# path_graph:返回一系列顺序节点,如果是整数n,那么就是0-n,也可以是包含节点信息的可迭代对象
H = nx.path_graph(10)
G.add_nodes_from(H)
nx.draw(G, with_labels=True)
img 2
网络图中的节点呈圆环排列,以上做法是把H的节点抢来放到G中,同样地,还可以把整个H作为G的一个节点,即一张包含了网络子图的网络图
G.add_node(H)
nx.draw(G, with_labels=True)
结果是生成的网络图中有一个节点写着path_graph(10)
,也就是所谓的graph of graph.
边
可以一次只加一条边
# 现在1、2节点上加一条边
G.add_edge(1, 2)
e = (2, 3)
# 如果是要写成元组形式,那么导入边时需要用*拆解
G.add_edge(*e)
nx.draw(G, with_labels=True)
img 4
可以同时加入一系列边
G.add_edges_from([(1, 3), (3, 5)])
nx.draw(G, with_labels=True)
img 5
移除所有的节点与边
# 移除所有的节点和边
G.clear()
nx.draw(G, with_labels=True)
会生成一个空图。
节点与边
只要指定边的关系,就会自动生成边关系里的节点,无需再次添加节点
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)
img 6
但是添加节点也不都是一样的,add_node
和add_nodes_from
差别很大
G.add_nodes_from('spam')
# 会添加四个节点:'s', 'p', 'a', 'm'
G.add_edge(3, 'm')
nx.draw(G, with_labels=True)
img 7
# 查看节点数量和边的数量
print G.number_of_nodes()
# 8
print G.number_of_edges()
# 3
对于节点、边的基础统计,最常见的是: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
# 展示出与某个节点存在直接联系的节点集合
# {'a': {}, 1: {2: {}, 3: {}}, 2: {1: {}}, 3: {1: {}, 'm': {}}, 'spam': {}, 'm': {3: {}}, 'p': {}, 's': {}}
print G.degree()
# 度:与某个节点有联系的节点数量
# {'a': 0, 1: 2, 2: 1, 3: 2, 'spam': 0, 'm': 1, 'p': 0, 's': 0}
还可以批量汇报基础统计量,类似于[nodeA, nodeB]
的查询方式叫做nbunch
,nbunch
可以是None(返回所有节点/边的信息),可以是单个节点,也可以是包含多个节点的可迭代对象。
print G.edges([2, 'm'])
# [(2, 1), ('m', 3)]
print G.degree([2, 3, 4])
# {2: 1, 3: 2}
# 因为没有节点4,所以返回结果中略过4
除了添加节点和边,也可以移除节点和边。
G.remove_node(2)
G.remove_nodes_from('spam')
nx.draw(G, with_labels=True)
原有的图瞬间少了很多节点,而且删除节点,对应的边也会消失。
img 8G.remove_edge(1, 3)
G.add_edge(1, "spam")
nx.draw(G, with_labels=True)
img 9
现在的网络都是无向的,当然还可以指定网络图的形式,比如构建有向网络。
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)
img 10
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)
img 11
今天就写到这里,还有别的事情要做……