力导布局图是一种用来展示节点以及节点之间网络关系数据的图表,其布局算法模型建立在粒子物理理论的基础上,将节点模拟成为原子,通过原子间的引力和斥力得到节点的速度与加速度,计算其移动方位与距离,达到一个稳定平衡的状态,从而完成布局,便于描述节点间关系。
今天的教程教大家使用pyecharts来绘制自动聚类的动态力导布局图(如上图)。
准备数据:
绘图所用的excel数据表格如下:
数据横行表示数据源节点,即发射数据的节点,纵行表示数据目标节点,即接收数据的节点。横行和竖行的内容实际上是完全一样的发明人名称。表格中的数据表示两两发明人之间的合作申请量。
绘图思路:
导入绘图所需的两个扩展包python-igraph和pyecharts;
python-igraph和pyecharts其实都是用于绘制力导布局图的,但是为什么需要两个扩展包呢?
因为pyecharts的力导布局图的算法没有办法实现计算机自动根据远近关系对节点(即发明人)进行聚类,而python-igraph可以实现自动聚类。但是python-igraph的图表没有pyecharts那么美。
所以结合两者优点,需要导入两个扩展包。首先采用python-igraph对从excel中读取的数据进行计算分类,对分类后的数据标记分类信息,继而调用pyecharts绘图。
具体步骤如下:
STEP1导入绘图所需要的扩展包
作图需安装如下两个额外扩展包:
STEP2利用python-igraph实现自动聚类
导入绘图所需包:
frompyechartsimportGraph#导入echarts库中的力导布局图
importpandasaspd#导入pandas,用于操作excel文件
importnumpyasnp#导入numpy库,用于数值计算
importigraph#导入python-igraph库,用于对数据聚类
使用pandas读入excel数据:
df=pd.read_excel('力导布局图.xlsx')#打开excel文件
将数据处理为规定格式及采用igraph扩展包分类:
g=igraph.Graph(1)#实例化一个igraph对象
g.add_vertices(df.index)#添加igraph顶点(就是力导布局图中的节点),数据来自excel文件的行索引
weights=[]#备用空列表,用于存储igraph聚类所需要的权重信息
my_links=[]#备用空列表,用于存储pyecharts的链接信息
foriindf.index:#外层循环,轮询excel每个列
forjindf.columns:#内层循环,轮询excel每一行
ifdf[j][i]>0:#大于0的值有效
my_links.append({'source':i,'target':(j),'value':df[j][i]})#从excel中读取数据,填入上面的备用列表中
g.add_edge(i,j)#添加边信息到igraph中,igraph的边对应pyecharts的links
weights.append(df[j][i])#添加权重信息到igraph的备用列表中
else:
pass#小于等于0的数不操作
ifnotg.vs[0]['name']:#判断igraph是否自动生成了‘None’顶点
g.delete_vertices(0)#删除None顶点
result=g.community_multilevel(weights,True)#运行聚类算法,结果存放在result变量里,包含两种聚类结果
igraph.plot(result[1],mark_groups=True,margin=20,
vertex_label=[str(i)foriinrange(len(df.index))])#根据聚类结果,使用igraph的绘图函数绘图,显示聚类结果
colors_list=['yellowgreen','gold','lightskyblue','lightcoral',
'darkslateblue','#ADD8E6','#DDA0DD',
'#FAA460','#F0E68C','#8c564b','#e377c2',
'#7f7f7f','#bcbd22','#17becf']#备用颜色列表
category_dic={}#备用空字典,存放每个顶点(节点)对应的分类
forlist_datainresult[1]:#取第一种聚类结果,循环访问聚类结果中的每一个“小团伙”
fordatainlist_data:#循环访问每一个“小团伙”中的顶点,以便标记团伙内的顶点的分类
category_dic[df.index[data]]=df.index[list_data[0]]#把“小团伙”内每个顶点标记为同一个分类,分类名称以团伙第一个认的名字命名,记录到备用字典中
sym_x=[]#备用空列表,用于存放excel中每一行的数据和,即该顶点向其他顶点发射的数据总和
sym_y=[]#备用空列表,用于存放excel中每一列的数据和,即该顶点接收其他顶点发射的数据总和
sym=[]#备用空列表,用于存放excel中每一个顶点所在的行列的数据值的和,即一个顶点发射和接收的数据总和
foriindf.index:#对每个顶点循环
sym_x.append(sum(df.loc[i]))#计算每个顶点的发射数据总和,填入备用列表
foriindf.columns:#对每个顶点循环
sym_y.append(sum(df[i]))#计算顶点的接收数据总和,填入备用列表
fora,binzip(sym_x,sym_y):#对每个顶点的发射和接收数据同时进行循环
sym.append(ab)#计算总和,填入备用列表
my_nodes=[{'name':i,'symbolSize':int(np.sqrt(j)*np.sqrt(max(sym))/max(sym)*25),
'category':category_dic[i],'value':j,'draggable':1}fori,jinzip(df.index,sym)]#生成节点数据,填入每个节点的名字,图标大小,分类,数据总数。
category=[{'name':df.index[i[0]]}foriinresult[1]]#pyecharts需要知道一共有多少种分类,固定格式
在这一过程中,会弹出python-igraph计算后分类生成的图片,如下:
上图中每个不同颜色的分组为计算机自动聚类的结果。这张图的每个小圆圈表示一个节点,节点内的数字代表这个节点点在excel行或者列中的顺序(其实就是代表一个发明人),当然也可以直接用文字代替数字显示,但是会很杂乱。
STEP3利用pyecharts利用分类后的数据绘图:
graph=Graph('合作关系图',width=1000,height=900)#实例化pyecharts里的力导布局图
graph.add('',my_nodes,my_links,category,graph_gravity=1.0,
is_legend_show=True,label_color=colors_list,
is_label_show=True,label_pos='right',line_curve=0)#绘制力导布局图,节点间距离通过graph_gravity参数调节。
graph.render('graph.html')#保存图表,在当前目录下生成‘graph.html’文件,需要手动用浏览器打开
STEP4生成HTML格式的动态图表
Pyecharts生成的所有图表均为html网页格式,手动用双击文件就可以通过浏览器打开。