从2.X迁移到3.0的迁移指南#
Note
在NetworkX 3.0发布之前的工作将包含在NetworkX 2.6、2.7和2.8的发布中。例如,我们在这些版本中正在弃用许多旧代码。本指南将讨论这一持续的工作,并帮助您了解现在可以做出哪些更改,以最小化由迁移到3.0引起的中断。
这是一份供从NetworkX 2.X迁移到NetworkX 3.0的人使用的指南。
这些问题可以在 邮件列表 上讨论。
3.0版本的重点是解决多年的技术债务,现代化我们的代码库,提高性能,并使贡献变得更加容易。 我们计划在夏季发布3.0版本。
默认依赖项#
我们不再依赖于”decorator”库,因此NetworkX不再有任何依赖项。
然而,NetworkX 3.0包括许多围绕与其他科学Python库(如 numpy 、 scipy 、 matplotlib 和 pandas )更紧密集成的变化和改进。
对于NetworkX的核心功能(如数据结构( Graph 、 DiGraph 等)和常见算法),没有任何依赖项,但是一些功能,例如 networkx.linalg 包中的函数,仅在安装了这些额外的库时才可用。
与科学Python更好地集成#
NetworkX 3.0包括几项改进和现代化 numpy 和 scipy 在networkx中的使用的变化。
删除矩阵语义 。
放弃所有对
numpy.matrix的使用,转而使用numpy.ndarray。采用scipy.sparse **array**接口。
默认使用NumPy或SciPy实现某些算法(例如pagerank) 。
numpy.random.Generator支持随机数生成。
用数组替换NumPy/SciPy矩阵#
长期以来, numpy.matrix 一直不被推荐使用,因为它与 ndarray 接口有显著差异,主要包括:
矩阵始终是二维的,导致在常见操作(如索引和广播)中产生不同的结果。
乘法运算符被解释为矩阵乘法,而不是逐元素乘法。
这些差异使得代码更难理解,并且通常需要样板代码才能处理多种格式。
随着scipy版本1.8中稀疏数组接口的添加,NetworkX 3.0已经用它们的数组对应物替换了所有scipy稀疏矩阵和numpy矩阵的实例。
在NetworkX 3.X中,任何返回 scipy.sparse.spmatrix 或 numpy.matrix 对象的函数现在将返回它们对应的数组版本(分别为 scipy.sparse._sparray 和 numpy.ndarray ),并且已删除导致矩阵对象的显式转换函数(例如 to_numpy_matrix )。用户应该期望所有 numpy 和 scipy.sparse 对象在NetworkX 3.X中遵循*array*语义。
切换到NumPy/SciPy实现作为某些算法的默认实现#
一些NetworkX分析算法可以使用线性代数实现非常高的性能,例如 pagerank 算法。在NetworkX 2.0中, pagerank 算法有多个实现版本: pagerank (纯Python实现)、 pagerank_numpy (用于稠密邻接矩阵)和 pagerank_scipy (稀疏邻接矩阵)。在所有实际用例中,SciPy实现远远优于其他实现。在NetworkX 3.0中, pagerank 函数现在默认使用SciPy实现。这意味着调用 nx.pagerank 现在需要安装SciPy。原始的Python实现仍可用于教学目的,命名为 networkx.algorithms.link_analysis.pagerank_alg._pagerank_python ,但不会公开暴露以阻止其使用。
支持 numpy.random.Generator#
NumPy v1.17引入了伪随机数生成的新接口。 py_random_state 和 np_random_state 装饰器已添加对新的 numpy.random.Generator 实例的支持;换句话说, seed 参数现在接受 numpy.random.Generator 实例:
>>> G = nx.barbell_graph(6, 2)
>>> pos = nx.spring_layout(G, seed=np.random.default_rng(123456789))
`numpy.random.Generator` 接口相比原始的 `numpy.random.RandomState` 包括几项改进,包括更好的统计特性和改进的性能。然而, ``Generator`` 与 ``RandomState`` 不兼容流式操作,并且不能保证与未来版本的NumPy兼容。因此,在使用随机数生成器时最佳实践是要明确。为了确保在NetworkX的所有版本(过去和未来)中**精确**可重现随机数,建议使用 ``RandomState`` ::
>>> rng = np.random.RandomState(12345)
>>> pos = nx.spring_layout(G, seed=rng)
对于不太重要的确切流复现性的新代码,建议使用 Generator
>>> rng = np.random.default_rng(12345)
>>> pos = nx.spring_layout(G, seed=rng)
Note
使用 Generator 实现确切的随机数复现仍然可能,但可能需要安装特定版本的numpy。
多属性邻接矩阵的NumPy结构化数据类型#
- 在NetworkX 3.0之前,通过
nx.to_numpy_recarray转换函数支持多属性邻接矩阵。 numpy.recarray是围绕ndarray的便利包装器,具有结构化数据类型。
因此,在NetworkX 3.0中,已删除此转换函数,并改为在 to_numpy_array 中添加对结构化数据类型的支持,通常改善了多属性邻接数组表示的支持:
>>> import numpy as np
>>> edges = [
... (0, 1, {"weight": 10, "cost": 2}),
... (1, 2, {"weight": 5, "cost": 100})
... ]
>>> G = nx.Graph(edges)
>>> # 创建具有"weight"和"cost"属性的邻接矩阵
>>> dtype = np.dtype([("weight", float), ("cost", int)])
>>> A = nx.to_numpy_array(G, dtype=dtype, weight=None)
>>> A
array([[( 0., 0), (10., 2), ( 0., 0)],
[(10., 2), ( 0., 0), ( 5., 100)],
[( 0., 0), ( 5., 100), ( 0., 0)]],
dtype=[('weight', '<f8'), ('cost', '<i8')])
>>> A["cost"]
array([[ 0, 2, 0],
[ 2, 0, 100],
[ 0, 100, 0]])
>>> # 可以使用 ``view`` 恢复recarray接口
>>> A = nx.to_numpy_array(G, dtype=dtype, weight=None).view(np.recarray)
>>> A
rec.array([[( 0., 0), (10., 2), ( 0., 0)],
[(10., 2), ( 0., 0), ( 5., 100)],
[( 0., 0), ( 5., 100), ( 0., 0)]],
dtype=[('weight', '<f8'), ('cost', '<i8')])
>>> A.weight
array([[ 0., 10., 0.],
[10., 0., 5.],
[ 0., 5., 0.]])
已弃用的代码#
函数 read_gpickle 和 write_gpickle 在3.0中已移除。
您可以将NetworkX图读取和写入为Python pickle。
>>> import pickle
>>> G = nx.path_graph(4)
>>> with open('test.gpickle', 'wb') as f:
... pickle.dump(G, f, pickle.HIGHEST_PROTOCOL)
...
>>> with open('test.gpickle', 'rb') as f:
... G = pickle.load(f)
...
函数 read_yaml 和 write_yaml 在3.0中已移除。
您可以使用pyyaml以YAML格式读取和写入NetworkX图。
>>> import yaml
>>> G = nx.path_graph(4)
>>> with open('test.yaml', 'w') as f:
... yaml.dump(G, f)
...
>>> with open('test.yaml', 'r') as f:
... G = yaml.load(f, Loader=yaml.Loader)