networkx画图(番外)——(1)自定义节点布局

networkx虽然非常方便,但在一些超大规模的图数据上,依然显得吃力。所以大多数时候,它仅仅是被用来做一些实例性的分析和可视化展示的,这需要学会如何灵活的画图。

最重要的就是布局,即每个节点在图上的什么位置。我们以 networkx学习与使用——(3)路与圈 中的ARPANET为例:
arpanet1970
但是,我们如何将其抽象成图之后仍能大致保留其原本的位置呢?构图上不需要太多的变化:

import networkx as nx               #载入networkx包
import matplotlib.pyplot as plt     #用于画图
G = nx.Graph()                     #无向图
edges = [('UCSB','SRI'),('UCSB','UCLA'),
        ('SRI','UCLA'),('SRI','STAN'),('SRI','UTAH'),
        ('UCLA','STAN'),('UCLA','RAND'),
        ('UTAH','SDC'),('UTAH','MIT'),
        ('RAND','SDC'),('RAND','BBN'),
        ('MIT','BBN'),('MIT','LINC'),
        ('BBN','HARV'),
        ('LINC','CASE'),
        ('HARV','CARN'),
        ('CASE','CARN')]
G.add_edges_from(edges)

主要是画图:

labels={}
for node in G.nodes():
    labels[node]=node
pos=nx.spring_layout(G)                     # 生成节点位置信息 
plt.rcParams['figure.figsize']= (6, 4)      # 设置画布大小
nx.draw_networkx_nodes(G,pos)               # 画节点
nx.draw_networkx_edges(G,pos)               # 画边
nx.draw_networkx_labels(G,pos,labels)       # 画标签 
plt.axis('off')                             # 去掉坐标刻度  
# 保存并显示图片
# plt.savefig("ARPA.png")
plt.show()

这里面影响节点布局的核心代码是:

pos=nx.spring_layout(G)                     # 生成节点位置信息 

这里使用的是networkx提供的自动生成节点位置的函数,其他常用的还有:

pos=nx.circular_layout(G)          # 生成圆形节点布局
pos=nx.random_layout(G)            # 生成随机节点布局
pos=nx.shell_layout(G)             # 生成同心圆节点布局
pos=nx.spring_layout(G)            # 利用Fruchterman-Reingold force-directed算法生成节点布局
pos=nx.spectral_layout(G)          # 利用图拉普拉斯特征向量生成节点布局
pos=nx.kamada_kawai_layout(G)      #使用Kamada-Kawai路径长度代价函数生成布局

我们将不同的布局都画出来:

labels={}
for node in G.nodes():
    labels[node]=node
pos_list = [nx.circular_layout(G), nx.random_layout(G), nx.shell_layout(G),
            nx.spring_layout(G), nx.spectral_layout(G), nx.kamada_kawai_layout(G)]    
plt.rcParams['figure.figsize']= (12, 6)      # 设置画布大小
for i,pos in enumerate(pos_list):
    ax1 = plt.subplot(2,3,i+1)
    nx.draw_networkx_nodes(G,pos)               # 画节点
    nx.draw_networkx_edges(G,pos)               # 画边
    nx.draw_networkx_labels(G,pos,labels)       # 画标签 
    plt.axis('off')                             # 去掉坐标刻度  
plt.show()

在这里插入图片描述
由于是这个图有实际的地理意义,我们会认为第四张和第六张看上去好看些,但还是不能满足我们的需求,因此我们希望能够自己定义这些位置。那么首先就要观察一下这个pos到底是什么,我们以spring_layout为例:

pos=nx.shell_layout(G)
print(pos)
out:{'UCSB': array([1.00000000e+00, 6.87745905e-09]), 'SRI': array([0.88545603, 0.46472317]), 
'UCLA': array([0.56806475, 0.82298386]), 'STAN': array([0.12053668, 0.99270886]),
'UTAH': array([-0.35460484,  0.93501627]), 'RAND': array([-0.74851078,  0.66312265]), 
'SDC': array([-0.97094184,  0.23931567]), 'MIT': array([-0.97094184, -0.23931561]),
'BBN': array([-0.74851084, -0.66312259]), 'LINC': array([-0.35460502, -0.93501621]),
'HARV': array([ 0.12053674, -0.99270886]), 'CASE': array([ 0.56806457, -0.82298398]), 
'CARN': array([ 0.88545603, -0.4647232 ])}

到这里应该就相对明了了,pos是一个字典,字典里的内容是个numpy的array(事实上,这里用列表和元组也是可以的),是一个二维的坐标,因此我们只需要更改这个坐标就能够得到一个和位置上符合原图的布局(我这里的布局是参照书上自己大概给个坐标画的)。

plt.rcParams['figure.figsize']= (12, 4)      # 设置画布大小
pos={'UCSB': [1.1,1.8], 'SRI': [2.4, 3.3], 
'UCLA': [2.4, 0.5], 'STAN': [3.4, 1.8],
'UTAH': [4.7,  3.3], 'RAND': [4.7,  0.5], 
'SDC': [5.3,  1.8], 'MIT': [8, 2.6],
'BBN': [8, 1.4], 'LINC': [9.5, 3.2],
'HARV': [ 9.5, 0.7], 'CASE': [11, 2.6], 
'CARN': [ 11, 1.4]} 
nx.draw_networkx_nodes(G,pos)               # 画节点
nx.draw_networkx_edges(G,pos)               # 画边
nx.draw_networkx_labels(G,pos,labels)       # 画标签 
plt.axis('off')                             # 去掉坐标刻度  
plt.show()

网络群体与市场P18页图2.3
这么看,是否好多了呢?当然,现实情况不可能一个个去填坐标,但是了解了pos的本质,我们就可以自己写random_layout这样简单的布局,或者根据自己的需求写一些布局,例如画推荐系统中的二部图,我们可以为将项目和用户的横坐标固定为不同值,只改变纵坐标。

完整代码资源

networkx画图(1)

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

I am having some problems in visualizing the graphs created with python-networkx, I want to able to reduce clutter and regulate the distance between the nodes (I have also tried spring_layout, it just... shell_layout:顶点在同心圆上分布 spring_layout:用Fruchterman-Reingold算法排列顶点 spectral_layout:根据图的Laplace特征向量排列顶点 circular_layout:环形布局算法。 random_layout:随机布局算法。 shell_layout:类似于环形布局布局算法,但是节点会被分为多层。 kamada_kawai_layout:基于牛顿迭代法的布局算法。 fruchterman_reingold_layout... 我们先通过nx.erdos_renyi_graph(10, 0.15)方法随机生成图像 er = nx.erdos_renyi_graph(10, 0.15) nx.draw(er,node_size=300,with_labels = True,pos = nx.spring_layout(er),node_color = 'r') pos常用自动布局函数 上图是由nx.draw(),核 networkx是一个用Python语言开发的图论与复杂网络建模工具,内置了常用的图与复杂网络分析算法,可以方便的进行复杂网络数据分析、仿真建模等工作。 利用networkx可以以标准化和非标准化的数据格式存储网络、生成多种随机网络和经典网络、分析网络结构、建立网络模型、设计新的网络算法、进行网络绘制等。 networkx支持创建简单无向图、有向图和多重图(multigraph);内置许多标准的图论算法,节点可为任意数据;支持任意的边值维度,功能丰富,简单易用。 networkx以图(graph)为基本数据 这几天在用networkx,官方文档是这个,很全也很详细,这里简单记录一些简单的用法和使用过程中的菜鸡看法。这篇主要记一下networkx基本图创建和如何画图。环境Python 3.6.3networkx 2.4matplotlib 2.1.0图的创建这里主要介绍一下networkx中定义的图结构,以及以无向图为例的用法。图的类型networkx中规定了四种图:无向图、有向图、多重无向图、多重有向... 定义一个包含两个GCN层的更深入的GCN模型第一层将大小为5的输入特征转化为大小为5的隐藏特征。再通过一个relu激活函数第二层转换隐藏层并产生大小为2的输出特征,对应空手道俱乐部的两组。第一个函数的参数分别表示:输入的特征大小、隐藏层的特征大小、以及输出的特征大小第二个函数的参数分别表示:图,图中节点的特征return h。 我所以理解的图布局:单纯nx.drwa()画出的图,保存后再打开会出现不一样的情况,所以需要布局来固定每个点的位置。一些布局的api可以直接看原博客:NetworkX系列教程(8)-Drawing Graph 如果只是简单使用nx.draw,是无法定制出自己需要的graph,并且这样的graph内的点坐标的不定的,运行一次变一次,实际中一般是要求固定的位置,这就需要到布局的概念了。详细的画图信息可以看这里。 networkx线性代数部分 由图打印出邻接矩阵list、特征值list; #定义图的 最近写论文画了许多图,在这里记录一些。当然,如果仅仅是展示性图片的话也可以使用visio,但是这里我仍然想探究一下如何使用pyhon画出美观的网络拓扑图。(1)根据邻接矩阵画出网络拓扑图(2)画出网络拓扑图,并对节点和链路进行表示,包括对节点和链路的标号,颜色区分,以及尺寸区分。 上一文中https://mp.csdn.net/postedit/80587923已经获取了节点的坐标,可以绘制平面道路网络图,不过在标识上由于图记使用了与节点一致的坐标,导致标记会覆盖节点,极不美观。上图是一个简单的道路平面网络,将所有坐标都根据其标记的位置,进行了调整,此外还加入了绘制形状、图例功能。 一、图标形状 绘制节点的函数为draw_networkx_nodes,其说明在...