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

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/

  • 16
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我的手机半斤重

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值