使用networkx绘制网络图及模块使用

主要练习了包和模块的生成,并且学习了各种可视化的操作方法,包括networkx库(对于网络的生成)、使用matplotlib、seaborn画柱形图,折线图等及对其的保存。同时,还学习了Gephi工具。

包的设计

包作为一个文件夹,需要在文件夹目录中添加一个__ init __.py文件,表示这是一个模块

一些在测试中使用的文件

模块节点操作

import csv
import networkx as nxdef init_node(path_node):#生成字典,每个id对应一个字典,字典里包含所有属性f=open(path_node,"r",encoding="utf-8")file=csv.reader(f)file = list(file)f.close()dict_user = {}  # 保存每个用户/节点的信息index = [0, 1, 2, 3, 4, 6, 7, 8]  # 表示对应每一个id的属性for item in file[1:]:info = {'views': "NAN", 'mature': "NAN", 'life_time': "NAN",'created_at': "NAN", 'updated_at': "NAN", 'dead_account': "NAN", 'language': "NAN", 'affiliate': "NAN"}for i in index:info[file[0][i]] = item[i]dict_user[item[5]] = inforeturn dict_user
#list(dict_user.keys())返回键def update_dict_user(dict_user,id,attribute,attribute_value):#之后要构建图之类的,可能需要对节点更新信息,之后发现貌似不需要dict_user[id][attribute] = attribute_valuereturn dict_userdef get_attribute(id,G,attribute):#输入节点的id,返回需要的属性值if attribute=="degree":ans=G.degree(id)else:ans=G.nodes[id][attribute]return ansdef print_node(G,id):print("id:{0:},{1:},'degree':{2:}".format(id, G.nodes[id],G.degree[id]))

改进方法:

#字典初始化
#为了达到该函数的普适性,我不希望在函数中出现具体属性的名字,而是通过索引的方式,当然id的位置可能没办法,但是当作为字典再去调用id的方式或者用列表索引的方式找id也是可以的,此处不再赘述
info=dict.fromkeys(file[0],"NAN")#前面表示key值,后面表示赋值

G的一些关于节点的函数

G.nodes()返回G的所有节点,如果要打印最好转为list形式

G.nodes[i] 返回节点的所有属性,且返回字典形式

G.degree[id]返回节点的度

对于打印所有的属性的函数,可以采用**dic[id],**调用可变长度的字典,或者*调用可变长度的元组

构建网络

import csvdef init_edge(path_edge):f = open(path_edge, "r", encoding="utf-8")file = csv.reader(f)file = list(file)edge_lis=file[1:]#排除第一行的列名f.close()return edge_lis

将边转化为构建图像使用的样式

import networkx as nx
import pickle as pickdef init_graph(dict_user,edge_lis):#对于传入的参数为id列表,因此需要对字典输出做一个键的列表化G=nx.Graph()#生成一个空白图for id in dict_user:for key in dict_user[id]:G.add_node(id)#插入点G.nodes[id][key]=dict_user[id][key]#添加属性G.add_edges_from(edge_lis)#连接节点return Gdef save_graph(G,path):f=open(path,"wb")#注意应该是二进制,因为序列化需要pick.dump(G,f)f.close()def load_graph(path):#反序列化需要将文件以二进制读取"rb",且load参数应为数据流f=open(path,"rb")result =pick.load(f)f.close()return result

说明:在init_graph函数里采用了两重循环,其实是比较费时的,但是这样可以保证输出的属性结果比较好看。

之后发现使用可变长度变量能够非常好的解决这个问题,最后也输出了同样的结果

for id in dict_user:G.add_node(id,**(dict_user[id]))#插入点

在使用序列化和反序列化的操作中,要注意两个点:1、解码和写入都用的是二进制方法。2、pickle.dump(序列化对象,文件指针),pickle.load(文件指针),而不是直接输入文件路径

构建完序列化的文件在之后可以直接拿来用,就不需要打开各种数据文件,重新生成一遍,会快很多,当我发现这个问题时,已经来不及了。。。

图像分析

import networkx as nxdef get_node_degree(id,G):#返回某一个节点的度ans=G.degree(id)return ansdef get_node_number(G):number=nx.number_of_nodes(G)return numberdef get_edge_number(G):number=nx.number_of_edges(G)return numberdef cal_average_degree(G):node=G.nodes()#返回degree列表sum=0for i in node:sum+=G.degree(i)ans=sum/len(node)return ansdef cal_degree_distribution(G):#返回度的分布序列degree_dis=nx.degree_histogram(G)#统计从0到最大度的频次lis = [z / float(sum(degree_dis)) for z in degree_dis]#生成密度列表return lisdef caL_view_distribution(G):view_dic={}for id in G.nodes():#生成字典view_dic[G.nodes[id]["views"]]=view_dic.get(G.nodes[id]["views"],0)+1sum=0for key in view_dic.keys():sum+=view_dic[key]for key in view_dic.keys():view_dic[key]=view_dic[key]/sumreturn view_dic

一些简单的计算和函数调用。

需要说明的就是几个函数:

nx.number_of_nodes(G)统计节点数,或者直接对节点列表取len也一样;nx.number_of_edges(G)取边的数量,或者直接使用G.edges()取列表长度也是一样的

nx.degree_histogram(G)统计的是图中所有的度,从0到最大度,如果为0则标0

词频统计的一个方法dict[key]=dict.get(key,0)+1;dict.keys() and dict.values() can return two lists.

可视化

可视化的方式有很多,当时考虑了一些处理数据的方式,毕竟数据量实在过于庞大,对于可视化的效果并不好

节点视图可视化

import networkx as nx
import matplotlib.pyplot as pltdef plot_ego_2(G,node):##由于有600多万条边和16万多点,这种画法如果在考虑度的角度,点就过多,考虑点的角度,度就过大plt.figure(figsize=(16,16))nx.draw_networkx_nodes(G,pos=nx.spring_layout(G),nodelist=node,node_color='r', label=True)  # 画节点nx.draw_networkx_edges(G,pos=nx.spring_layout(G))  # 画边plt.axis('off')  # 去掉坐标刻度plt.savefig("D:\\经管大三\\现代程序设计\\week4\\ego_2.png")plt.show()def plot_ego(G,node):res=G.subgraph(node)nx.draw_networkx(res,pos=nx.spring_layout(res))plt.savefig("D:\\经管大三\\现代程序设计\\week4\\ego.png")plt.show()def plot_ego_3(G,node):res = G.subgraph(node)nx.draw(res,pos = nx.circular_layout(G),node_color = 'b',edge_color = 'r',with_labels = True,font_size =10,node_size =20)plt.savefig("D:\\经管大三\\现代程序设计\\week4\\ego_3.png")plt.show()def plotdegree_distribution(degree_dis):x=[i for i in range(len(degree_dis))]#生成横坐标y=degree_disx2=[i for i in range(100)]#因为通过可视化发现100的分布较多,而由于度上限很大,使得该部分分布密集y2=degree_dis[0:100]plt.subplot(1,2,1)plt.plot(x,y,color="red",linewidth=3.0)plt.title("degree distribution")plt.xlabel("degree")plt.ylabel("scale")plt.subplot(1,2,2)plt.plot(x2,y2,color="blue",linewidth=3.0)plt.title("degree distribution")plt.xlabel("degree")plt.ylabel("scale")plt.show()
for i in G.nodes():if G.degree(i)==60:id=ibreak
lis1=[id]
neighbor=list(G.neighbors(id))
lis1=lis1+neighbor
H=G.subgraph(lis1)#返回结果不错
nx.draw(H,pos=nx.circular_layout(H),with_labels= True)
plt.show()

单纯的从度的角度或者节点的角度出发结果并不是很好

问题最大的地方不在于如何画图,在于如何选取点,最后发现采用上述方法找度为60的点及其邻接点,在这种情况下将会产生61个点,利用subgraph绘制子图即可。下图中我们可以看出82是与其他节点连接最密集的节点,当然我们找的度为60的节点就是82!

函数详解

plt.figure() 对画布窗口的设置

nx.draw_networkx_nodes(G,pos=nx.spring_layout(G),nodelist=node,node_color=‘r’, label=True)
nx.draw_networkx_edges(G,pos=nx.spring_layout(G))

G我认为更像一个网络图的画布,我们可以通过draw函数在上面任意加点和线,利用draw_networkx_nodes 和draw_networkx_edges可以自定义网络图,pos表示绘图的方式,有五种基本的绘图方式,nodelist表示绘制点的列表,在绘制边的函数参数中也可以如此添加

我从同学那又看到一个筛选节点的方法,就是直接在图上删除节点G.remove_node(i)

plt.axis()设置坐标轴格式;plt.show()展示绘制的视图;plt.savefig(file)可以将图片按照希望的格式保存,也可以保存为矢量图

下面是绘制度的分布图:

如果对所有的度进行统计会发现差别特别大,度大于某一个值之后分布变化及其不明显,因此我将0-100的度分出,做一个局部的分析判断。结果显示有大量的节点并没有邻接点,且随着度的增大有明显的下降趋势。

其中用了plt.subplot()函数用来实现子图处理;plt.plo()t画折线图

网络图可视化

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import networkx as nx
#第一版的plot方法由于x轴太密
import matplotlib.ticker as ticker
import mathdef plot_nodes_attribute(G,attribute):node=G.nodes()key=['views', 'mature', 'life_time', 'created_at', 'updated_at', 'numeric_id', 'dead_account', 'language', 'affiliate']if attribute in key:key_dic={}for id in node:key_dic[G.nodes[id][attribute]]=key_dic.get(G.nodes[id][attribute],0)+1#画图x=list(key_dic.keys())y=list(key_dic.values())length=math.floor(len(x)/7)ax=sns.barplot(x,y)ax.xaxis.set_major_locator(ticker.MultipleLocator(base=length))  # 解决X轴密集问题plt.title(f"{attribute:}")plt.savefig(f"D:\\经管大三\\现代程序设计\\week4\\{attribute:}分布.png")elif attribute == "degree":y=nx.degree_histogram(G)x=[i for i in range(len(y))]length = math.floor(len(x) / 7)ax=sns.barplot(x, y)ax.xaxis.set_major_locator(ticker.MultipleLocator(base=length))  # 解决X轴密集问题plt.title(f"{attribute:}")plt.savefig(f"D:\\经管大三\\现代程序设计\\week4\\{attribute:}分布.png")else:print("not find")def plot_nodes_attribute_2(G,attribute):#画直方图和拟合曲线node=G.nodes()key=['views', 'mature', 'life_time', 'created_at', 'updated_at', 'numeric_id', 'dead_account', 'language', 'affiliate']if attribute in key:lis=[]for id in node:lis.append(G.nodes[id][attribute])#画图length = math.floor(len(lis) / 7)#由于间隔太密,因此提取部分x轴坐标ax=sns.distplot(lis,kde=True,rug=True)ax.xaxis.set_major_locator(ticker.MultipleLocator(base=length))  # 解决X轴密集问题plt.title(f"{attribute:}")plt.savefig(f"D:\\经管大三\\现代程序设计\\week4\\{attribute:}分布_2.png")elif attribute == "degree":lid=[]for id in node:lid.append(G.degree(id))sns.distplot(lid)plt.title(f"{attribute:}")plt.savefig(f"D:\\经管大三\\现代程序设计\\week4\\{attribute:}分布_2.png")else:print("not find")

以上函数的编写部分我觉得简洁性欠佳,其实可以对之前显示节点所有属性的模块函数进行调用,这样就不需要重新提取属性了。最开始做的时候,发现没有注意坐标轴的问题,导致坐标轴相互交叠根本看不清楚。

length = math.floor(len(lis) / 7)#由于间隔太密,因此提取部分x轴坐标
ax=sns.distplot(lis,kde=True,rug=True)
ax.xaxis.set_major_locator(ticker.MultipleLocator(base=length))  # 解决X轴密集问题

因此我的处理方式就是将所有可能值的总长度分成7段,计算每段的长度,设置x轴的格式来进行简化

第一个函数用了sns.bar(x,y)绘制条形图,第二个函数用sns.distplot(lis,kde=True,rug=True)绘制条形图和拟合曲线,kde=True表示绘制核密度,rug=True表示用直线表示核密度

main函数

import GraphStat.Networkbuilder.node as GNN
import GraphStat.Networkbuilder.edge as GNE
import GraphStat.Networkbuilder.graph as GNG
import GraphStat.Networkbuilder.stat as GNS
import GraphStat.Visualization.plotgraph as GVP
import GraphStat.Visualization.plotnodes as GVNpath="D:\\经管大三\\现代程序设计\\week4\\twitch_gamers\\large_twitch_features.csv"
path2="D:\\经管大三\\现代程序设计\\week4\\twitch_gamers\\large_twitch_edges.csv"
path3="D:\\经管大三\\现代程序设计\\week4\\G.txt"
dic=GNN.init_node(path)
edge=GNE.init_edge(path2)
G=GNG.init_graph(dic,edge)
#GNN.print_node(G,"8000")
#ans=GNN.get_attribute("8000",G,"language")
#print(ans)
#X=GNS.get_edge_number(G)
#Y=GNS.get_node_number(G)
#Z=GNS.caL_view_distribution(G)
#Q=GNS.cal_average_degree(G)
#W=GNS.cal_degree_distribution(G)
#E=GNS.get_node_degree("8000",G)
#node=[]
#for i in G.nodes():#   if G.degree(i)==120:#之前以度为标定#      node.append(i)
#GVP.plot_ego_3(G,node)
#GVP.plotdegree_distribution(W)
GVN.plot_nodes_attribute(G,"views")

Gephi工具的使用以及对图的处理

最开始提取了前50个id,想要返回他们子图的边的关系,但是发现子图中只有一条边,这显然是不符合要求的

path1="D:\\经管大三\\现代程序设计\\week4\\twitch_gamers\\large_twitch_features.csv"
#path2="D:\\经管大三\\现代程序设计\\week4\\twitch_gamers\\large_twitch_edges.csv"
path3="D:\\经管大三\\现代程序设计\\week4\\Gephi_node.csv"
path4="D:\\经管大三\\现代程序设计\\week4\\Gephi_edge.csv"
f1=open(path1,"r",encoding="utf-8")
#f2=open(path2,"r",encoding="utf-8")
lis1=list(csv.reader(f1))
lis1=[item[5] for item in lis1[1:51]]#惊奇的发现这个数据似乎是按照id的增序排列的,这么干好像又多此一举了
#lis2=list(csv.reader(f2))
G=GNG.load_graph("D:\\经管大三\\现代程序设计\\week4\\G.txt")
H=G.subgraph(lis1)
print(list(H.edges))
f1.close()
#f2.close()
#我们在使用Gephi时发现随机抽取边使得点的数量爆炸,哪怕只抽了100000条边,因此搜索一些边来进行操作
f1=open(path3,"w",encoding="utf-8",newline='')
f2=open(path4,"w",encoding="utf-8",newline='')#newline=''参数可以防止多余的换行
g1=csv.writer(f1)
g2=csv.writer(f2)
g1.writerow(lis1[0])
g1.writerows(lis1[1:201])
#g2.writerow(lis2[0])
#g2.writerows(lis2[1:100001])

于是我决定选择一个度为60的节点,然后反向寻找该节点的邻接点,生成一个新的子图

import csv
import GraphStat.Networkbuilder.graph as GNG
import networkx as nxpath3="D:\\经管大三\\现代程序设计\\week4\\Gephi_node.csv"#Gephi貌似只处理csv文件
path4="D:\\经管大三\\现代程序设计\\week4\\Gephi_edge.csv"#对于Gephi工具传入边的关系自动分析
G=GNG.load_graph("D:\\经管大三\\现代程序设计\\week4\\G.txt")
for i in G.nodes():if G.degree(i)==60:id=ibreak
lis1=[id]
neighbor=list(G.neighbors(id))
lis1=lis1+neighbor
H=G.subgraph(lis1)#返回结果不错
for it in range(len(lis1)):lis1[it]=[lis1[it]]#这一步是为了生成csv文件
H_edges=list(H.edges)
f1=open(path3,"w",encoding="utf-8",newline='')
f2=open(path4,"w",encoding="utf-8",newline='')#newline=''参数可以防止多余的换行
g1=csv.writer(f1)
g2=csv.writer(f2)
init_edge=["node1","node2"]
g1.writerow(["node"])
g1.writerows(lis1)
g2.writerow(init_edge)
g2.writerows(H_edges)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X9VKoTFn-1664261383998)(D:\经管大三\现代程序设计\week4\Gephi子图测试.png)]

id))
lis1=lis1+neighbor
H=G.subgraph(lis1)#返回结果不错
for it in range(len(lis1)):
lis1[it]=[lis1[it]]#这一步是为了生成csv文件
H_edges=list(H.edges)
f1=open(path3,“w”,encoding=“utf-8”,newline=‘’)
f2=open(path4,“w”,encoding=“utf-8”,newline=‘’)#newline=''参数可以防止多余的换行
g1=csv.writer(f1)
g2=csv.writer(f2)
init_edge=[“node1”,“node2”]
g1.writerow([“node”])
g1.writerows(lis1)
g2.writerow(init_edge)
g2.writerows(H_edges)

![在这里插入图片描述](https://img-blog.csdnimg.cn/34479c9022744efc8dbf7cc91fca890c.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/d32fd66562da488e8d12fd148fd43026.png#pic_center)

使用networkx绘制网络图及模块使用相关推荐

  1. 【科学文献计量】networkx绘制网络图的基本属性,图形读写以及无向/有向图形绘制详解

    networkx绘制网络图基本属性,图形读写以及无向/有向图形绘制详解 1 Properties of graph 图像属性 1.1 案例 1.2 代码详解 2 Read and write grap ...

  2. python画有权重网络图_Python可视化之NetworkX绘制网络图\节点关系

    除了Gephi,python的NetworkX也是绘制网络图的利器,后者功能更强大,能兼容Gephi的一些绘制结果,但相应学习成本也更高点.另外似乎还有一个igraph-python库,后期可以学习一 ...

  3. Python networkx 绘制网络图简介

    转自:http://www.cnblogs.com/huiyang865/p/5677449.html 绘制基本网络图 用matplotlib绘制网络图 基本流程: 1. 导入networkx,mat ...

  4. networkx绘制网络图的知识点

    1.创建一个空的无向图 import networkx as nx import matplotlib.pyplot as plt G = nx.Graph() G.clear() # 清空图上的元素 ...

  5. [python] 基于NetworkX实现网络图的绘制

    文章目录 NETWORK CHART(网络图) 1. 自pandas基础网格图绘制 Basic Network from pandas data frame 2. 自定义NetworkX图形外观 Cu ...

  6. python画有权重网络图_使用Python的networkx绘制精美网络图教程

    最近因为数学建模3天速成Python,然后做了一道网络的题,要画网络图.在网上找了一些,发现都是一些很基础的丑陋红点图,并且关于网络的一些算法也没有讲,于是自己进http://networkx.git ...

  7. 用python画关系网络图-使用Python的networkx绘制精美网络图教程

    最近因为数学建模3天速成Python,然后做了一道网络的题,要画网络图.在网上找了一些,发现都是一些很基础的丑陋红点图,并且关于网络的一些算法也没有讲,于是自己进http://networkx.git ...

  8. 使用networkx绘制社交网络图

    使用networkx绘制社交网络图 lot as plt 代码如下. import networkx as nx # 导入networkx import matplotlib.pyplot as pl ...

  9. 利用Gephi软件绘制网络图

    文章目录 利用Gephi软件绘制网络图 1. 生成物种相关性矩阵 2. Gephi生成点.边文件 3. 点.边文件注释 4. 网络点.边美化 5. 网络属性.预览和标签 参考文献 猜你喜欢 写在后面 ...

最新文章

  1. 奇葩注释大盘点,你觉得哪个最牛逼?
  2. Error ./include/caffe/util/mkl_alternate.hpp:11:19: fatal error: cblas.h: 没有那个文件或目录...
  3. 用python计算2+4+6+…+20的值_计算2*3+(2*(5+6)*3)/2+4*6的值
  4. CSDN博客下载器v2.0发布(导出PDF)
  5. 谷歌翻译插件安装使用
  6. 直流电机正反转驱动电路
  7. 小爱音箱怎么装app_小爱音箱最新版本下载  小爱音箱app介绍_2113手游
  8. 纠错码专题——线性分组码(1)
  9. 小马哥linux网络培训,linux基础入门
  10. 数据结构-快速排序 C语言源码
  11. ubuntu下格式化被写保护的U盘
  12. VEH +硬件断点 HOOK
  13. HTML <caption> 标签
  14. 别再吐槽12306了!有本事你来写架构
  15. 如何在 3dMax 中制作游戏中的战斧模型?
  16. 【云原生】Grafana 介绍与实战操作
  17. win10自动更新导致显卡驱动出问题,No AMD Graphics driver is installed or.......的解决方案
  18. 【Unity开发】随手记:点击屏幕选中物体
  19. 微信红包随机数字_微信随机红包数详解和算法代码
  20. CSS是什么?CSS样式规则

热门文章

  1. Oracle中tablesinfo_Oracle X$Tables | 學步園
  2. 【酷QC++】如何利用酷Q制作一个机器人?
  3. 互联网发展十几年,你错过了哪些创业机会
  4. 《算法图解》——第五章 散列表(服务器大姨妈来了?第四第五内容传不上去= =!)
  5. 小凡实验室卧龙老师CCIE学习方法:CCIE涅槃五剑
  6. 【sql 统计实例】统计本月,本年,去年
  7. 清理计算机磁盘碎片,电脑磁盘碎片清理我帮你
  8. 最小的语言符号是A词B语素C音素D义素,2018年10月自考《语言学概论》模拟试题(8)...
  9. 【项目总结】之——JS分割字符串
  10. python网络爬虫--项目实战--scrapy爬取人人车(5)