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

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

最重要的就是布局,即每个节点在图上的什么位置。我们以networkx学习与使用——(3)路与圈中的ARPANET为例:

但是,我们如何将其抽象成图之后仍能大致保留其原本的位置呢?构图上不需要太多的变化:

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]=nodepos=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]=nodepos_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()


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

完整代码资源

networkx画图(1)

参考

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

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

  1. 我的世界mod开发(3番外)自定义方块/物品模型

    Blockbench下载 先做一个模型(图片与模型名字要相同): 按Ctrl+S把模型放置在 src\main\resources\assets\fmltutor\models\block (src\ ...

  2. networkx 画图布局

    举例 import networkx as nx import matplotlib.pyplot as plt 我们先通过nx.erdos_renyi_graph(10, 0.15)方法随机生成图像 ...

  3. CORS跨域时axios无法获取服务器自定义的header信息 - 番外篇

    已解决CORS跨域时axios无法获取服务器自定义的header信息?! 先看代码: // 登录后的表单提交ajaxRegisterApi: function (form) { var key = l ...

  4. 20.番外篇——Vue如何自定义组件并且进行全局配置

    20.番外篇--如何自定义组件并且进行全局配置 前言 1.创建自定义组件 2.导出自定义组件 3.main.js中引入自定义的公共组件并挂在到Vue 4.使用自定义的公共组件 前言 通过之前的系列文章 ...

  5. 番外:设置自定义字体

    番外:css中设置自定义字体(引入字体) 1.常规下(你自己有字体包的情况下) 假设你的文件夹这个样子: font文件夹下有两个字体文件,此时你想使用zkkh.ttf(站酷酷黑字体) 代码如下: &l ...

  6. 【番外篇】ASP.NET MVC快速入门之免费jQuery控件库(MVC5+EF6)

    目录 [第一篇]ASP.NET MVC快速入门之数据库操作(MVC5+EF6) [第二篇]ASP.NET MVC快速入门之数据注解(MVC5+EF6) [第三篇]ASP.NET MVC快速入门之安全策 ...

  7. clang static analyzer源码分析(番外篇):RegionStore以及evalCall()中的conservativeEvalCall

    引子 我们在上一篇文章<clang static analyzer源码分析(番外篇):evalCall()中的inline机制>中提及了clang如何创建CallGraph,如何进行函数i ...

  8. java优先队列的入队函数,算法与数据结构番外(1):优先队列

    这是算法与数据结构番外系列的第一篇,这个系列未来的主要内容是补充一些与算法与数据结构相关的知识,这些知识比较零碎,同时也与正传关系密切,往往需要阅读了正传的相关内容以后,才能较好的理解这部分内容.如果 ...

  9. 教你从0到1搭建秒杀系统-Canal快速入门(番外篇)

    Canal用途很广,并且上手非常简单,小伙伴们在平时完成公司的需求时,很有可能会用到.本篇介绍一下数据库中间件Canal的使用. 很多时候为了缩短调用延时,我们会对部分接口数据加入了缓存.一旦这些数据 ...

最新文章

  1. C++中的常引用、常对象、常函数、常数据成员
  2. 基于固态激光雷达Livox的建图与定位系统!提供Docker自测!
  3. linux手写数字识别opencv,opencv实现KNN手写数字的识别
  4. EXCEL教程,包你一学就会
  5. MySQL使用distinct去掉查询结果重复的记录
  6. Ubuntu字符界面输入密码始终提示错误 login incorrect 解决办法
  7. using 语句中使用的类型必须可隐式转换为“System.IDisposable“
  8. python判断进程是否存在
  9. mysql存储过程局部变量使用_MySQL存储过程使用输出变量
  10. 刚发布!开发者调查报告:机器学习/深度学习算法工程师急缺
  11. c语言右上左下遍历数组,如何将一个数组的元素循环左移?
  12. SpringAOP 学习笔记
  13. 现代法谱估计(3)Burg算法MATLAB及Python实现
  14. Bootstrap 实例1
  15. 基于小波变换的音频压缩
  16. MySQL数据库之设置密码修改密码用户名
  17. CF #768 F.Flipping Range
  18. 如何实现在退休时有足够的钱供老年任性花费?(复利年金通胀综合案例)
  19. AttributeError: module ‘torch.distributed‘ has no attribute ‘_all_gather_base‘
  20. 基于改进层次凝聚聚类算法的垃圾收运跨区域调度策略

热门文章

  1. Vi,Java,Ant,Junit的自学报告
  2. C#,图论与图算法,寻找图强连通单元(Strongly Connected Components)的罗伯特·塔扬(Robert Tarjan‘s Algorithm)算法与源程序
  3. 如何通过云效Projex让项目协作任务不再千篇一律
  4. 2023年某科技公司前端开发初级岗的面试笔试真题(含选择题答案、问答题解析、机试题源码)
  5. css小鸡破壳,小班美术教案《小鸡破壳》
  6. npm ERR! code ERESOLVEnpm ERR! ERESOLVE could not resolve dependency
  7. 长文慎入!经验分享-专科毕业5年,成功入职腾讯!
  8. 2018 Java 后端工程师的书单推荐
  9. debian linux iso下载工具,debian 8.7系统下载
  10. Treble 架构下的 Android Camera 框架