Networkx简介
Networkx是一款基于python的开源软件包,主要用于复杂关系网络(Complex Network Analysis)分析和图计算(Graph Processing),其主要功能包括创建、操作和学习复杂关系网络的结构,基于复杂关系网络进行执行图算法等,是一款非常常用的图计算开源软件包之一。复杂网络分析有许多用途,例如分析社交网络中的关系、反洗钱、风险识别和欺诈检测、以及新冠肺炎流行期间用于密接排查等。本文主要简单介绍一下Networkx的使用方法,具体的使用细节可以参考Networkx的官方操作文档,内容十分详尽。
Graph的创建
在Networkx中,Graph是所有操作的属主,是Node和Edge的集合。其中图又分成以下四种,分别是Graph,DiGraph,MultiGraph和MultiDiGraph,四者的区别如下:
Networkx Class | Type | Self-loops allowed | Parallel edges allowed |
---|---|---|---|
Graph | undirected | Yes | No |
DiGraph | directed | Yes | No |
MultiGraph | undirected | Yes | Yes |
MultiDiGraph | directed | Yes | Yes |
总结一下就是:
- Networkx中Graph分有向图和无向图。
- Networkx中所有的图都支持自环,即允许有某个顶点指向当前顶点的边存在。
- MultiGraph和MultiDigraph是支持平行边的,即两个顶点间具有两条(同向)的边。
Graph的创建十分简单,在进行任何图操作之前,需要先创建一个图:
import networkx as nx
G = nx.Graph()
G = nx.DiGraph()
G = nx.MultiGraph()
G = nx.MultiDiGraph()
除了默认创建空图之外,networkx还支持使用使用现有的图,node或edge列表以及邻接数组等直接进行图的创建,例如:
# create a DiGraph using the connections from G
G.add_edge(1, 2)
H = nx.DiGraph(G)
# create a graph from an edge list
edgelist = [(0, 1), (1, 2), (2, 3)]
H = nx.Graph(edgelist)
# create a Graph dict mapping nodes to nbrs
adjacency_dict = {0: (1, 2), 1: (0, 2), 2: (0, 1)}
H = nx.Graph(adjacency_dict)
添加nodes
在Networkx中,任何hashable的对象都可以成为node,比如一个字符串、一副图像和一个xml对象,甚至是另外一个Graph对象或一个自定义的node对象等。为Graph添加node有多种方式,比如一次添加一个node:
G.add_node(1)
或者使用list一次添加多个node:
G.add_nodes_from([2, 3])
以上两种方式添加的node只有唯一的id,没有任何属性,networkx也支持添加具有属性的顶点,如向图中添加了两个id分别为4,5,属性为color,属性值分别为红色和绿色的顶点。:
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
除了上述添加node的方式之外,还支持从另外一个图中添加node,即把另外一个图中的node过来作为新图的node:
H = nx.path_graph(10)
G.add_nodes_from(H)
当然,我们之前说过,图本身也可以作为一个node,因此我们还可以这样:
G.add_node(H)
但是这样添加之后,图G中只有一个顶点为H这个图的顶点。这种灵活性非常重要,也非常有用,比如在计算模块度(Modularity)的时候,需要不断的对原图中的node进行聚合,将聚合的子图重新视是为一个新的顶点,并参与到下一轮的迭代中。
另外还有种添加node的方式,即在添加edge的时候,如果这个node在图中不存在,就会自动添加到这个图中,如果存在就忽略。
添加edges
类似与向图中添加nodes,向图中添加一条edge:
G.add_edge(1, 2)
e = (2, 3)
G.add_edge(*e) # unpack edge tuple*
如果当前图G中不存在node 1 和 2 ,那么此时也会将1,2作为node添加到图G中。
另外还可以通过list向图中添加多条edge:
G.add_edges_from([(1, 2), (1, 3)])
或者也可以将另外一个图中的edges添加到当前图中:
G.add_edges_from(H.edges)
在Graph和DiGraph中,networkx会自动忽略掉已经存在node、edge。例如:
G.add_edges_from([(1, 2), (1, 3)])
G.add_node(1)
G.add_edge(2, 1)
G.add_node("spam") # adds node "spam"
G.add_nodes_from("spam") # adds 4 nodes: 's', 'p', 'a', 'm'
G.add_edge(3, 'm')
这个时候我们去看这个图中有多少node和edge,发现结果是8和3,因为重复的node和edge都被自动忽略掉了。
G.number_of_nodes(), G.number_of_edges()
(8,3)
为graph、node和edge添加属性
上面我们所创建的graph、node和edge除了有唯一可区分的id外,并不具有任何属性,下面介绍如何为graph、node和edge添加属性。我们可以用下列方式创建一个带有属性的图G:
G = nx.Graph(day="Friday")
然后我们可以修改这个Graph的属性:
G.graph['day'] = "Sunday"
可以用下来方法创建并修改node的属性:
#add nodes with attributes
G.add_node(1, time='5pm')
G.add_nodes_from([3, 4], time='2pm')
#modify attribute of node
G.nodes[1]['room'] = 714
可以用下来方法创建并修改edge的属性:
#add edges with attributes
G.add_edge(1, 2, weight=4.7 )
G.add_edges_from([(3, 4), (4, 5)], color='red')
G.add_edges_from([(1, 2, {'color': 'blue'}), (2, 3, {'weight': 8})])
#modify attribute of edges
G[1][2]['weight'] = 4.7
G.edges[3, 4]['weight'] = 4.2
关于图的创建就简单介绍这么多,至于DiGraph、MultiGraph、和MultiDiGraph的具体创建不同,可以通过对比四种不同图直接的差异进行类推,整体上差不多,只是在一些networkx内部做了一些去重,以及去重方式不一样而已,比如在Graph中,依次添加边(1,2)和边(2,1)的效果是其实等同于就添加了一条边(1,2),而在MultiGraph中,会添加两条边;另外在DiGraph和MultiDiGraph中(1,2)和(2,1)会视为两条不同的边添加到图中。好了,就这么多,以后慢慢介绍如何利用networkx进行图分析和图展示。