利用Python中的networkx画复杂网络图
老师给了任务要画几个复杂网络的图,无奈MATLAB作图实在太麻烦,于是花了一个周末研究怎么画图。下面简单介绍python的第三方库NetworkX
NetworkX
NetworkX是一个用于创建,操作和研究复杂网络的结构,动态和功能的Python包。使用NetworkX,我们可以使用标准和非标准数据格式加载和存储网络,生成多种类型的随机和经典网络,分析网络结构,构建网络模型,设计新的网络算法,绘制网络等等。
基础教程
创建一个图
以下代码用来创建空图:
import networkx as nx
G = nx.Graph()
在这里,Graph
是点与边的集合,点的种类有许多,它可以是任何哈希对象:字符串、图像、XML对象、另一个Graph
...
点
我们可以一次插入一个点:G.add_node(1)
也可以直接从list中插入一系列点:G.add_nodes_from()
同样,你也可以把图H当做一个点插入到G中:G.add_node(H)
边
一次插入一条边:G.add_edge(1, 2)
同插入点,可以从list中插入一系列边:G.add_edges_from([(1, 2), (1, 3)])
删除/清空
如果想删除图中某特定的点或边,这里有类似上分add的命令:
G.remove_node()
G.remove_nodes_from()
G.remove_edge()
G.remove_edges_from
清空图G中的所有点与边,这个命令相比大家都能猜到,没错,就是G.clear()
注:
以上省略了许多内容,且只考虑了无向无权图,更具体的教程还请移步:NetworkX
下面介绍个人认为NetworkX中的重点!
图生成器和图操作
除了以点与边生成图之外,还有以下方式创造图:
1. 典型图的操作命令:
subgraph(G, nbunch) - 由图G的分支nbunch生成子图
union(G1,G2) - 将图G1,G2结合构成一个图
disjoint_union(G1,G2) - 假设所有的节点都不相同构成图
cartesian_product(G1,G2) - 由笛卡尔积生成图
compose(G1,G2) - 结合两个图中共有的点构成图
complement(G) - 图的补
create_empty_copy(G) - 返回相同图类的空副本
convert_to_undirected(G) - 返回G的无向图表示
convert_to_directed(G) - 返回G的有向图表示
2. 典型小图的命令:
复杂网络领域有一些经典的网络图供大家当做示例研究。以下只是部分:
petersen = nx.petersen_graph()
tutte = nx.tutte_graph()
maze = nx.sedgewick_maze_graph()
tet = nx.tetrahedral_graph()
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.使用通用图形格式(如edge表,邻接表,GML,GraphML,pickle,LEDA等)读取存储在文件中的图形:
nx.write_gml(red, "path.to.file")
mygraph = nx.read_gml("path.to.file")
更多关于图的格式与生成器函数的信息请移步:
Reading and writing graphs
Graph generators
图的分析
networkx提供了一些关于图论的函数来帮助你分析图的特征:
>>> G = nx.Graph()
>>> G.add_edges_from([(1, 2), (1, 3)])
>>> G.add_node("spam") # 加入点“spam”
>>> list(nx.connected_components(G))
[set([1, 2, 3]), set(['spam'])]
>>> sorted(d for n, d in G.degree())
[0, 1, 1, 2]
>>> nx.clustering(G)
{1: 0, 2: 0, 3: 0, 'spam': 0}
一些具有较大输出的函数迭代(节点,值)二元组。 这些很容易存储在一个dict
结构中:
>>> sp = dict(nx.all_pairs_shortest_path(G))
>>> sp[3]
{1: [3, 1], 2: [3, 1, 2], 3: [3]}
如何画复杂网络图
NetworkX主要不是一个图形绘制软件包,但它包含Matplotlib的基本绘图以及使用开源Graphviz软件包的界面。 这些是networkx.drawing模块的一部分。首先引入matplotlib:import matplotlib.pyplot as plt
最基础的一个函数是nx.draw(G, pos=None, ax=None, **kwds)
,其中pos即图中各点的位置信息,这里我们就要用到以下几个函数来以某种算法生成各店的坐标:
-
circular_layout(G[, scale, center, dim])
:Position nodes on a circle. -
random_layout(G[, center, dim])
:Position nodes uniformly at random in the unit square. -
rescale_layout(pos[, scale])
:Return scaled position array to (-scale, scale) in all axes. -
shell_layout(G[, nlist, scale, center, dim])
:Position nodes in concentric circles. -
spring_layout(G[, k, pos, fixed, …])
:Position nodes using Fruchterman-Reingold force-directed algorithm. -
spectral_layout(G[, weight, scale, center, dim])
:Position nodes using the eigenvectors of the graph Laplacian.
当然,除了使用draw直接将整个图画出来,你也可以利用draw_networkx_nodes, draw_networkx_edges, draw_networkx_labels等有选择性的分别画出网络的点、边、标签等等。
当然,最后不要忘记:plt.show()