NetworkX是一款Python的软件包,用于创造、操作复杂网络,以及学习复杂网络的结构、动力学及其功能。 有了NetworkX你就可以用标准或者不标准的数据格式加载或者存储网络,它可以产生许多种类的随机网络或经典网络,也可以分析网络结构,建立网络模型,设计新的网络算法,绘制网络等等。 如果在此之前你还不太了解Python,戳这里——>
其实如果要用NetworkX来进行复杂网络的编程还离不开许多相关的其他Python库,我们可以去官网根据需求一一安装,有详细的安装说明。这里推荐一种超级方便实用的方法,即安装Anaconda,Anaconda包含了许多实用的常用Python库,你就不需要再一一自己安装了。请参考。(Anaconda是跨平台的Windows和Linux都支持)
(下面实验如果没有特殊说明,都是在Ubuntu下使用Visual Studio Code实验的)
import networkx as nx
G = nx.Graph()
根据图的定义,一个图包含一个节点集合和一个边集。在NetworkX中,节点可以是任何哈希对象,像一个文本字符串,一幅图像,一个XML对象,甚至是另一个图或任意定制的节点对象。(注意,Python中的None对象是不可以作为节点的类型的。)H=nx.path_graph(10) #H是一个有10个节点的链状图,即有n个节点n-1条边的连通图
G.add_nodes_from(H) #或者G.add_nodes_from(H.nodes())
此时图G中就包含了图H中的10个节点。作为比较,我们可以使图H作为图G的一个节点:
`G.add_node(H)`
现在图G就包含了一个节点H,即该节点是一个图。可以看到这种灵活性是非常强大的,它允许图的图,文件的图,函数的图等等。因此我们应该好好思考如何构建我们的应用程序才能使我们的节点是有用的实体。当然我们可以在图中使用一个唯一的标识符或者使用一个不同的字典的键来标识节点信息。(如果该hash依赖于它的内容,则我们不应该改变节点对象)G.add_edge(1,2)
#等价于
e=(1,2) #e是一个元组
G.add_edge(*e) #这是python中解包裹的过程
也可以通过添加list来添加多条边:
G.add_edges_from([(1,2),(1,3)])
或者通过添加任何ebunch来添加边,一个ebunch是任何可迭代的边的元组,一个边的元组可以是两个节点之间的一个2元组(无权值的边)或者3元组(3元组还有一个元素是边的权值,比如(1,2,{‘weight’:100}))。下面将进一步讨论边的属性:
G.add_edges_from(H.edges()) #不能写作G.add_edges_from(H)
我们可以用类似的方法拆除图:G.remove_node(),G.remove_nodes_from(),G.remove_edge(),G.remove_edges_from() 比如:
G.remove_node(H)
如果你添加的节点和边是已经存在的,是不会报错的。比如,我们先将图G里的所有节点和边删除:
G.clear()
然后我们新的节点和边,NetworkX会自动忽略掉已经存在的边和节点的添加:
G.add_edges_from([(1,2),(1,3)])
G.add_node(1)
G.add_edge(1,2)
G.add_node("spam") #添加节点"spam"
G.add_nodes_from("spam") #添加节点's' 'p' 'a' 'm'
此时图G一共有8个节点和2条边。 我们可以通过如下函数查看:
print G.number_of_nodes()
print G.number_of_edges()
此时对应的网络G的图形为:我们还可以查阅当前图G的实际情况:
当我们通过某一种图类创建一个图形结构的实例时,我们可以指定好几种不同格式的数据:
但是我们可以很安全的去改变一条已存在的边的属性(权值):
如果想要快速遍历每一条边,我们可以使用邻接迭代器实现,对于无向图,每一条边相当于两条有向边:
(add_weight_edges_from函数的作用是通过一个ebunch添加一些节点和边,边默认其属性为”weight”) 说明:其实FG.adjacency_iter()返回的是一个所有节点的二元组(node, adjacency dict)的迭代器,比如上述代码中对于节点1返回的是:(1,{2:{0.125},3:{0.75}})。 一种方便的访问所有边的方法:
给图、节点和边添加属性 属性诸如weight,labels,colors,或者任何对象,你都可以附加到图、节点或边上。 对于每一个图、节点和边都可以在关联的属性字典中保存一个(多个)键-值对。默认情况下这些是一个空的字典,但是我们可以增加或者是改变这些属性通过使用add_edge,add_node或者字典操作这些属性字典,比如G.graph,G.node或者G.edge。
有些算法只能在有向图中使用,而有些图并没有为有向图定义。确实将有向图和无向图混在在一起是很危险的一件事情,所以,如果有些实验你想把一个有向图看做一个无向图,你可以将有向图转化为无向图,通过:
H=DG.to_undirected()
#或者
H=nx.Graph(DG)
多图(Multigraphs) NetworkX提供了一个类,它可以允许任何一对节点之间有多条边。类MultiGraph和类MultiDiGraph允许添加相同的边两次,这两条边可能附带不同的权值。对于有些应用程序这是非常有用的类,但是许多算法不能够很好的在这样的图中定义,比如最短路径算法,但是像MultiGraph.degree这种算法又可以很好的被定义。否则你应该为了很好的定义测量,而将图转化为标准的图。
图的生成器和图的操作 除了通过节点和边生成图,也可以通过以下方法产生:
petersen=nx.petersen_graph()
tutte=nx.tutte_graph()
maze=nx.sedgewick_maze_graph()
tet=nx.tetrahedral_graph()
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)
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)
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"
>>> nx.connected_components(G)
[[1, 2, 3], ['spam']]
>>> sorted(nx.degree(G).values())
[0, 1, 1, 2]
>>> nx.clustering(G)
{<!-- -->1: 0.0, 2: 0.0, 3: 0.0, 'spam': 0.0}
返回节点属性的函数是通过返回一个以节点为键的字典来实现的:
>>> nx.degree(G)
{1: 2, 2: 1, 3: 1, 'spam': 0}
对于一些特定节点的值,我们可以提供该特定节点(集)的nbunch作为函数参数。如果被指定的是单个节点,则返回一个对应的单一的值,如果被指定的是一个nbunch,则返回一个字典:
>>> nx.degree(G,1)
2
>>> G.degree(1)
2
>>> G.degree([1,2])
{<!-- -->1: 2, 2: 1}
>>> sorted(G.degree([1,2]).values())
[1, 2]
>>> sorted(G.degree().values())
[0, 1, 1, 2]
绘制图 NetworkX并不是专门用来绘图的包,但是Matplotlib以及一些接口却提供了很好的绘图功能。Python3.0以上的版本可能不能很好的兼容NetworkX中的绘图包。
首先我们导入Matplotlib的plot接口(pylab也可以)
import matplotlib.pyplot as plt
#或者
import matplotlib.pylab as plt
你可能会发现使用“ipthon -pylab”q去交互测试代码是很有用的,它提供了强大的ipython和matplotlib,也提供了一个方便的交互模式。
测试networkx.drawing是是否导入成功,可以通过:
nx.draw(G)
nx.draw_random(G)
nx.draw_circular(G)
nx.draw_spectral(G)
你要将这个图形绘制到屏幕,你可能需要Matplotlib:
plt.show()
如果你不需要显示,那你可以将图像保存到一个文件:
nx.draw(G)
plt.savefig("path.png")
最基础的NetworkX的介绍和使用说明到这里就先结束了,后期还会继续学习更深入的NetworkX和复杂网络相结合的相关用法。