教程

参考文献

0 简单介绍

图的类型

  • Graph类是无向图的基类,无向图能有自己的属性或参数,不包含重边,允许有回路,节点可以是任何hash的python对象,节点和边可以保存key/value属性对。该类的构造函数为Graph(data=None,**attr),其中data可以是边列表,或任意一个Networkx的图对象,默认为none;attr是关键字参数,例如key=value对形式的属性。
  • MultiGraph是可以有重边的无向图,其它和Graph类似。其构造函数MultiGraph(data=None, *attr)。
  • DiGraph是有向图的基类,有向图可以有数自己的属性或参数,不包含重边,允许有回路;节点可以是任何hash的python对象,边和节点可含key/value属性对。该类的构造函数DiGraph(data=None,**attr),其中data可以是边列表,或任意一个Networkx的图对象,默认为none;attr是关键字参数,例如key=value对形式的属性。
  • MultiDiGraph是可以有重边的有向图,其它和DiGraph类似。其构造函数MultiDiGraph(data=None, *attr)

有向图

这个 DiGraph 提供了附加的属性,DiGraph.out_edges , DiGraph.in_degree , DiGraph.predecessors() , DiGraph.successors() 等。为了使算法能够轻松地与两个类一起工作,有向版本的 neighbors() 等于 successors() 虽然 degree 报告 in_degree 和 out_degree 尽管有时会觉得不一致。

1
2
3
4
5
6
7
8
9
10
DG = nx.DiGraph()
DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)])
DG.out_degree(1, weight='weight')
0.5
DG.degree(1, weight='weight')
1.25
list(DG.successors(1))
[2]
list(DG.neighbors(1))
[2]

有向图和无向图的转换

1
2
Graph.to_undirected()
H = nx.Graph(G) # create an undirected graph H from a directed graph G

多重图

多重图
NetworkX为允许任意节点对之间存在多个边的图形提供类。这个 MultiGraph 和 MultiDiGraph 类允许您两次添加相同的边缘,可能使用不同的边缘数据。这对某些应用程序来说可能很强大,但许多算法在此类图上没有很好的定义。如果结果定义明确,例如: MultiGraph.degree() 我们提供功能。否则,您应该以一种使测量定义良好的方式转换为标准图。

1
2
3
4
5
6
7
8
9
10
11
12
MG = nx.MultiGraph()
MG.add_weighted_edges_from([(1, 2, 0.5), (1, 2, 0.75), (2, 3, 0.5)])
dict(MG.degree(weight='weight'))
{1: 1.25, 2: 1.75, 3: 0.5}
GG = nx.Graph()
for n, nbrs in MG.adjacency():
for nbr, edict in nbrs.items():
minvalue = min([d['weight'] for d in edict.values()])
GG.add_edge(n, nbr, weight = minvalue)

nx.shortest_path(GG, 1, 3)
[1, 2, 3]

1 增加

创建图形

创建一个没有节点和边的空图形。

1
2
3
>>>
import networkx as nx
G = nx.Graph()

根据定义,a Graph 是一组节点(顶点)和已识别的节点对(称为边、链接等)的集合。在NetworkX中,节点可以是任何 hashable 对象,例如文本字符串、图像、XML对象、另一个图形、自定义节点对象等

添加节点

图 G 可以通过多种方式生长。NetworkX包括许多图形生成器功能和以多种格式读取和写入图形的工具。我们先来看看简单的操作。

  • 一次添加一个节点,
1
G.add_node(1)
  • 从任何 iterable 容器,如列表
1
G.add_nodes_from([2, 3])
  • 如果容器产生2个元组形式,还可以添加节点和节点属性 (node, node_attribute_dict) ::
1
2
3
4
G.add_nodes_from([
(4, {"color": "red"}),
(5, {"color": "green"}),
])
  • 一个图中的节点可以合并到另一个图中
1
2
H = nx.path_graph(10)
G.add_nodes_from(H)
  • G 现在包含的节点 H 作为节点 G . 相反,您可以使用图表 H 作为一个节点 G .
1
G.add_node(H)

添加边缘

  • G 也可以通过一次添加一个边来生长,
1
2
3
G.add_edge(1, 2)
e = (2, 3)
G.add_edge(*e) # unpack edge tuple*
  • 通过添加边列表,
1
G.add_edges_from([(1, 2), (1, 3)])
  • 我们添加新的节点/边缘,忽略已经存在的节点和边
1
2
3
4
5
6
7
>>>
G.add_edges_from([(1, 2), (1, 3)])
G.add_node(1) # 已经存在1节点,不再重复添加
G.add_edge(1, 2) # 已经存在1,2边,不再重复添加
G.add_node("spam") # adds node "spam"
G.add_nodes_from("spam") # adds 4 nodes: 's', 'p', 'a', 'm'
G.add_edge(3, 'm')
  • 在这个阶段,图表 G 由8个节点和3个边组成,如下所示:
1
2
3
4
5
>>>
G.number_of_nodes()
8
G.number_of_edges()
3

2 删除

删除元素

可以用与添加类似的方式从图形中删除节点和边。

  • Graph.remove_node()
  • Graph.remove_nodes_from()
  • Graph.remove_edge()
  • Graph.remove_edges_from()
1
2
3
4
5
6
>>>
G.remove_node(2)
G.remove_nodes_from("spam")
list(G.nodes)
[1, 3, 'spam']
G.remove_edge(1, 3)

构造函数

图形对象不必以增量方式构建——指定图形结构的数据可以直接传递给各种图形类的构造函数。当通过实例化一个图形类来创建一个图结构时,可以用几种格式指定数据。

1
2
3
4
5
6
G.add_edge(1, 2)
H = nx.DiGraph(G) # create a DiGraph using the connections from G
list(H.edges())
[(1, 2), (2, 1)]
edgelist = [(0, 1), (1, 2), (2, 3)]
H = nx.Graph(edgelist)

3 查找

访问边缘和邻居

  • 除了视图 Graph.edges 和 Graph.adj ,可以使用下标表示法访问边和邻居。
1
2
3
4
5
6
7
G = nx.Graph([(1, 2, {"color": "yellow"})])
G[1] # same as G.adj[1]
AtlasView({2: {'color': 'yellow'}})
G[1][2]
{'color': 'yellow'}
G.edges[1, 2]
{'color': 'yellow'}
  • 如果边已经存在,可以使用下标表示法获取/设置边的属性。
1
2
3
4
5
G.add_edge(1, 3)
G[1][3]['color'] = "blue"
G.edges[1, 2]['color'] = "red"
G.edges[1, 2]
{'color': 'red'}
  • 使用 G.adjacency() 或 G.adj.items() . 注意,对于无向图,邻接迭代可以看到每个边两次。
1
2
3
4
5
6
7
8
9
10
FG = nx.Graph()
FG.add_weighted_edges_from([(1, 2, 0.125), (1, 3, 0.75), (2, 4, 1.2), (3, 4, 0.375)])
for n, nbrs in FG.adj.items():
for nbr, eattr in nbrs.items():
wt = eattr['weight']
if wt < 0.5: print(f"({n}, {nbr}, {wt:.3})")
(1, 2, 0.125)
(2, 1, 0.125)
(3, 4, 0.375)
(4, 3, 0.375)
  • 使用边缘属性可以方便地访问所有边缘。
1
2
3
4
5
for (u, v, wt) in FG.edges.data('weight'):
if wt < 0.5:
print(f"({u}, {v}, {wt:.3})")
(1, 2, 0.125)
(3, 4, 0.375)

4 修改

向图形、节点和边添加属性

诸如权重、标签、颜色或任何您喜欢的python对象等属性都可以附加到图形、节点或边上。

每个图、节点和边都可以在关联的属性字典中保存键/值属性对(键必须是可哈希的)。默认情况下,这些属性为空,但可以使用 add_edge , add_node 或直接操作命名的属性字典 G.graph , G.nodes 和 G.edges 对于图 G .

图形属性

创建新图形时分配图形属性

1
2
3
G = nx.Graph(day="Friday")
G.graph
{'day': 'Friday'}

或者您可以稍后修改属性

1
2
3
G.graph['day'] = "Monday"
G.graph
{'day': 'Monday'}

节点属性

使用添加节点属性 add_node() , add_nodes_from() 或 G.nodes

1
2
3
4
5
6
7
G.add_node(1, time='5pm')
G.add_nodes_from([3], time='2pm')
G.nodes[1]
{'time': '5pm'}
G.nodes[1]['room'] = 714
G.nodes.data()
NodeDataView({1: {'time': '5pm', 'room': 714}, 3: {'time': '2pm'&#125;&#125;)

请注意,将节点添加到 G.nodes 不将其添加到图表中,使用 G.add_node() 添加新节点。同样适用于边缘。

边缘属性

使用添加/更改边缘属性 add_edge() , add_edges_from() 或下标符号。

1
2
3
4
5
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})])
G[1][2]['weight'] = 4.7
G.edges[3, 4]['weight'] = 4.2

特殊属性 weight 应该是数字,因为它被需要加权边缘的算法使用。