您当前的位置: 首页 > 技术文章 > 移动开发

networkx 中文学习手册

作者: 时间:2022-11-26阅读数:人阅读

创建图表

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

import networkx as nx
G = nx.Graph()

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

节点

G可以通过多种方式增长。 NetworkX 包括许多
图形生成器函数和
以多种格式读取和写入图形的工具。
首先,我们将看看简单的操作。 您可以添加一个节点
一次,

G.add_node(1)

或从任何 iterable 容器添加节点,例如列表

G.add_nodes_from([2, 3])

还可以添加节点以及节点
如果容器产生表单的 2 元组,则属性
(node, node_attribute_dict):

>>> G.add_nodes_from([
...     (4, {"color": "red"}),
...     (5, {"color": "green"}),
... ])

节点属性将在下面进一步讨论。

一个图中的节点可以合并到另一个图中:

H = nx.path_graph(10)
G.add_nodes_from(H)

G 现在包含 H 的节点作为 G 的节点。
相比之下,您可以将图形 H用作G中的节点。

G.add_node(H)

G现在包含H作为一个节点。 这种灵活性非常强大,因为
它允许图形图形、文件图形、函数图形等等。
值得考虑如何构建您的应用程序,以便节点
是有用的实体。 当然你总是可以在G中使用唯一标识符
并且有一个单独的字典,由标识符键控到节点信息,如果
你比较喜欢。

G 也可以通过一次添加一条边来增长,

G.add_edge(1, 2)
e = (2, 3)
G.add_edge(*e)  # unpack edge tuple*

通过添加边列表,

G.add_edges_from([(1, 2), (1, 3)])

或者通过添加任何边缘。 ebunch 是任何可迭代的
边缘元组的容器。 边元组可以是节点的 2 元组或 3 元组
带有 2 个节点,后跟一个边属性字典,例如,
(2, 3, {'weight': 3.1415})。 进一步讨论边缘属性
以下。

G.add_edges_from(H.edges)

There are no complaints when adding existing nodes or edges. For example,
after removing all nodes and edges,

G.clear()

我们添加新的节点/边,NetworkX 会悄悄地忽略任何
已经存在。

G.add_edges_from([(1, 2), (1, 3)])
G.add_node(1)
G.add_edge(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 个边组成,如下所示:

G.number_of_nodes()
G.number_of_edges()
3
DG = nx.DiGraph()
DG.add_edge(2, 1)   # adds the nodes in order 2, 1
DG.add_edge(1, 3)
DG.add_edge(2, 4)
DG.add_edge(1, 2)
assert list(DG.successors(2)) == [1, 4]
assert list(DG.edges) == [(2, 1), (2, 4), (1, 3), (1, 2)]

检查图的元素

我们可以检查节点和边。 四个基本图形属性有助于
报告:G.nodesG.edgesG.adjG.degree。 这些
是节点、边、邻居(邻接)和度的类似集合的视图
图中的节点数。 它们提供持续更新的只读视图
图结构。 它们也类似于 dict,因为您可以查找节点
通过视图和边缘数据属性并使用数据属性进行迭代
使用方法.items().data()
如果您想要一个特定的容器类型而不是一个视图,您可以指定一个。
这里我们使用列表,尽管集合、字典、元组和其他容器可能是
在其他情况下更好。

list(G.nodes)
list(G.edges)
list(G.adj[1])  # or list(G.neighbors(1))
G.degree[1]  # the number of edges incident to 1
2

可以指定从所有节点的子集中报告边和度
使用 nbunch。 nbunch 是以下任何一个:None(意味着所有节点),
一个节点,或一个可迭代的节点容器,它本身不是
图形。

G.edges([2, 'm'])
G.degree([2, 3])
DegreeView({2: 1, 3: 2})

从图中删除元素

可以以与添加类似的方式从图中删除节点和边。
使用方法
Graph.remove_node(),
Graph.remove_nodes_from(),
Graph.remove_edge()

Graph.remove_edges_from(),例如

G.remove_node(2)
G.remove_nodes_from("spam")
list(G.nodes)
G.remove_edge(1, 3)

使用图构造函数

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

G.add_edge(1, 2)
H = nx.DiGraph(G)  # create a DiGraph using the connections from G
list(H.edges())
edgelist = [(0, 1), (1, 2), (2, 3)]
H = nx.Graph(edgelist)  # create a graph from an edge list
list(H.edges())
adjacency_dict = {0: (1, 2), 1: (0, 2), 2: (0, 1)}
H = nx.Graph(adjacency_dict)  # create a Graph dict mapping nodes to nbrs
list(H.edges())
[(0, 1), (0, 2), (1, 2)]

什么用作节点和边

您可能会注意到节点和边未指定为 NetworkX
对象。 这使您可以自由地使用有意义的项目作为节点和
边缘。 最常见的选择是数字或字符串,但节点可以
是任何可散列对象(“None”除外),并且可以关联边
使用G.add_edge(n1, n2, object=x)的任何对象x

例如,n1n2 可以是来自 RCSB Protein 的蛋白质对象
数据库,“x”可以指出版物的 XML 记录,详细说明
他们相互作用的实验观察。

我们发现这个异能非常有用,但它的滥用
除非熟悉 Python,否则可能会导致令人惊讶的行为。
如果有疑问,请考虑使用 convert_node_labels_to_integers() 来获得
带有整数标签的更传统的图形。

访问边和邻居

除了视图Graph.edgesGraph.adj
使用下标符号可以访问边和邻居。

G = nx.Graph([(1, 2, {"color": "yellow"})])
G[1]  # same as G.adj[1]
G[1][2]
G.edges[1, 2]
{'color': 'yellow'}

您可以使用下标符号获取/设置边的属性
如果边缘已经存在。

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()
请注意,对于无向图,邻接迭代会看到每条边两次。

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)

使用 edge 属性可以方便地访问所有边。

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)

向图、节点和边添加属性

诸如权重、标签、颜色或任何您喜欢的 Python 对象之类的属性,
可以附加到图、节点或边。

每个图、节点和边都可以在关联的
属性字典(键必须是可散列的)。 默认情况下,这些是空的,
但是可以使用 add_edgeadd_node 或直接添加或更改属性
操作名为“G.graph”、“G.nodes”和
图形“G”的“G.edges”。

图形属性

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

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

或者您可以稍后修改属性

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

节点属性

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

G.add_node(1, time='5pm')
G.add_nodes_from([3], time='2pm')
G.nodes[1]
G.nodes[1]['room'] = 714
G.nodes.data()
NodeDataView({1: {'time': '5pm', 'room': 714}, 3: {'time': '2pm'}})

请注意,将节点添加到 G.nodes 不会将其添加到图形中,请使用
G.add_node() 添加新节点。 边缘也是如此。

边缘属性

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

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 应该是数字,因为它被使用
需要加权边的算法。

有向图

DiGraph 类提供特定的附加方法和属性
到有向边,例如,
DiGraph.out_edgesDiGraph.in_degree
DiGraph.predecessorsDiGraph.successors 等。
为了让算法能够轻松地处理这两个类,有向版本的
neighbors 等价于
successorsdegree 报告总和
in_degreeout_degree 即使有时感觉不一致。

DG = nx.DiGraph()
DG.add_weighted_edges_from([(1, 2, 0.5), (3, 1, 0.75)])
DG.out_degree(1, weight='weight')
DG.degree(1, weight='weight')
list(DG.successors(1))
list(DG.neighbors(1))
[2]

一些算法仅适用于有向图,而其他算法效果不佳
为有向图定义。 确实有肿块导向的倾向
和无向图放在一起是危险的。 如果你想治疗
对于某些测量,您可能应该将有向图视为无向图
使用 Graph.to_undirected() 或使用

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

多图

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

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'))
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. 应用经典的图操作,例如:

2. 使用对经典小图之一的调用,例如,

3. 对经典图使用(构造性)生成器,例如,

像这样:

K_5 = nx.complete_graph(5)
K_3_5 = nx.complete_bipartite_graph(3, 5)
barbell = nx.barbell_graph(10, 10)
lollipop = nx.lollipop_graph(10, 20)

4. 使用随机图生成器,例如,

像这样:

er = nx.erdos_renyi_graph(100, 0.15)
ws = nx.watts_strogatz_graph(30, 3, 0.1)
ba = nx.barabasi_albert_graph(100, 5)
red = nx.random_lobster(100, 0.9, 0.9)

5. 使用常见的图形格式读取存储在文件中的图形

NetworkX 支持许多流行的格式,例如边缘列表、邻接列表、
GML、GraphML、pickle、LEDA 等。

nx.write_gml(red, "path.to.file")
mygraph = nx.read_gml("path.to.file")

有关图形格式的详细信息,请参阅阅读和编写图形
对于图形生成器功能,请参阅图形生成器

分析图表

可以使用各种图论来分析 G 的结构
功能,例如:

G = nx.Graph()
G.add_edges_from([(1, 2), (1, 3)])
G.add_node("spam")       # adds node "spam"
list(nx.connected_components(G))
sorted(d for n, d in G.degree())
nx.clustering(G)
{1: 0, 2: 0, 3: 0, 'spam': 0}

一些具有大输出的函数迭代 (node, value) 2 元组。
如果您愿意,这些很容易存储在 dict 结构中。

sp = dict(nx.all_pairs_shortest_path(G))
sp[3]
{3: [3], 1: [3, 1], 2: [3, 1, 2]}

有关图算法的详细信息,请参阅算法
支持的。

绘制图形

NetworkX 主要不是图形绘图包,而是基本绘图
Matplotlib 以及使用开源 Graphviz 软件的接口
包都包括在内。 这些是 networkx.drawing 的一部分
模块,如果可能,将被导入。

首先导入 Matplotlib 的绘图界面(pylab 也可以)

import matplotlib.pyplot as plt

测试nx_pylab的导入是否成功绘制G
使用其中之一

G = nx.petersen_graph()
subax1 = plt.subplot(121)
nx.draw(G, with_labels=True, font_weight='bold')
subax2 = plt.subplot(122)
nx.draw_shell(G, nlist=[range(5, 10), range(5)], with_labels=True, font_weight='bold')

在这里插入图片描述

绘制到交互式显示器时。 请注意,您可能需要发出
Matplotlib

plt.show()

命令,如果您不在交互模式下使用 matplotlib(请参阅
这个 Matplotlib 常见问题解答)。

options = {
    'node_color': 'black',
    'node_size': 100,
    'width': 3,
}
subax1 = plt.subplot(221)
nx.draw_random(G, **options)
subax2 = plt.subplot(222)
nx.draw_circular(G, **options)
subax3 = plt.subplot(223)
nx.draw_spectral(G, **options)
subax4 = plt.subplot(224)
nx.draw_shell(G, nlist=[range(5,10), range(5)], **options)

在这里插入图片描述

您可以通过 draw_networkx()
通过“布局模块”进行布局。
您可以通过draw_shell() 使用多个shell。

G = nx.dodecahedral_graph()
shells = [[2, 3, 4, 5, 6], [8, 1, 0, 19, 18, 17, 16, 15, 14, 7], [9, 10, 11, 12, 13]]
nx.draw_shell(G, nlist=shells, **options)

在这里插入图片描述

要将图纸保存到文件,请使用,例如

nx.draw(G)
plt.savefig("path.png")

在这里插入图片描述

此函数写入本地目录中的文件“path.png”。 如果 Graphviz 和
PyGraphviz 或 pydot,在您的系统上可用,您也可以使用
networkx.drawing.nx_agraph.graphviz_layout
networkx.drawing.nx_pydot.graphviz_layout 获取节点位置,或者写
点格式的图形以供进一步处理。

from networkx.drawing.nx_pydot import write_dot
pos = nx.nx_agraph.graphviz_layout(G)
nx.draw(G, pos=pos)
write_dot(G, 'file.dot')

在这里插入图片描述

networkx官网:https://networkx.org/

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:licqi@yunshuaiweb.com

加载中~
如果您对我们的成果表示认同并且觉得对你有所帮助可以给我们捐赠。您的帮助是对我们最大的支持和动力!
捐赠我们
扫码支持 扫码支持
扫码捐赠,你说多少就多少
2
5
10
20
50
自定义
您当前余额:元
支付宝
微信
余额

打开支付宝扫一扫,即可进行扫码捐赠哦

打开微信扫一扫,即可进行扫码捐赠哦

打开QQ钱包扫一扫,即可进行扫码捐赠哦