内容简介:利用graphtool进行图的可视化处理
最近恶心的项目中期检查,我被分配到做社交图的分析,然而事实上我并不知道弄啥。虽然不是我自己答辩,但是考虑到还是不要太坑dalao,我决定不管怎样至少得搞点图撑撑场面免得尴尬,这几天就赶鸭子上架倒腾了下 graph_tool
这个专门用于对图进行可视化的 python 库。虽然网上中文资料不足,但是他的英文文档还是非常全面的,很多设计的小细节也在文档里提及了,非常简单容易上手。下面就从一个初学者的记录下我的学习历程。
安装
虽然是个python库,但是毕竟是要做大量数据计算的,因此graphtool在底层使用了Boost, CGAL 和 expat这几个C++库(Boost是扩展的标准库,CGAL是一个计算几何算法库,expat是一个XML解析器)。这就导致了使用通常的pip和easyinstall不太好直接安装。正确的安装姿势大概有三种:
- 使用Docker
- 源码安装
- 各个 Linux 版本的包管理器
这里主要参考 graph-tool installation 的各种安装说明。
从最基本的源码安装,到封装好的包管理器安装,再到最万金油的 docker 安装一应俱全。
看上去一片美好。
然而真正用的时候发现,如果使用docker,官方提供的镜像还是太过庞大,用起来还是太臃肿了;如果采用更新源+包管理器安装的化,要是系统的版本比较新还好,要是系统版本老了,就会报各种依赖不足的问题。。。最坑爹的是,即使采用源码安装的方式,由于开发人员比较勤快,经常更新技术,很多库都需要较新的版本,容易导致老的机器上无法编译,而且由于项目源码是托管在他自己搭的 git服务器 上,这个服务器还很坑,旧的版本经常下不下来。。。最近不知道为什么官网的服务器崩了,还好我之前下了源码,于是把他fork到了我的 github 上,做个备份。
不过还好,虽然我的服务器比较旧,但是我的台式机比较新,没啥问题。。。
函数结构
这个项目的文档非常详尽,可以参考他的 quickstart ,类的API在 这里 。下面稍微整理下大概用途,方便查找:
graph_tool | 主要用于是图的加载、构建、删除、持久化、迭代 |
graph_tool.centrality | 主要用于计算与图的中心度相关的信息 |
graph_tool.clustering | 主要用于计算图的各种聚类系数 |
graph_tool.collection | 保存了十几个供参考的数据集 |
graph_tool.correlations | 主要用与计算各种相关度信息 |
graph_tool.draw | 封装了一些常用的绘图算法 |
graph_tool.flow | 处理图的最大流最小割一类的问题 |
graph_tool.generation | 主要用于预先生成一些图,比如完全图,随机图,晶格图等等 |
graph_tool.inference | 主要用于推断图的社区结构 |
graph_tool.search | 包装了一些图的搜索算法,比如bfs,dijikstra,astar等等 |
graph_tool.spectral | 主要用于计算图的矩阵信息 |
graph_tool.stats | 主要用于图的简单直方图统计等信息 |
graph_tool.topology | 主要包装了图的拓扑性质,比如最短路,最小生成树,拓扑 排序 等等 |
graph_tool.util | 主要是一些节点和边的查找方法 |
简单说明
图的构建
- graph-tool支持有向图和无向图,默认是无向图,他将节点用一个编号表示,边用开始节点和终结点的编号来表示。节点编号下标从0开始递增,并始终从0开始保持连续。
- 当我们删除一个节点时,实际上是将这个节点与最后一个节点交换索引,然后将总的编号减一。因此当我们迭代删除的时候,要按照节点编号逆序遍历删除。
- graph-tool为方便保存图的信息,采用的是压缩的xml来进行图的持久化存储,用这个格式来保存图还是比较高效的,我们要率先考虑。
- 使用这个库的时候我们尽量不要写循环语句,比如节点度数的统计信息等。因为就和numpy一样,绝大多数需要循环的操作他都提供了并且做了优化,我们需要做的就是找到这个函数。
PropertyMap对象
这个对象是 graph_tool
封装的一个映射工具,文档在 这里 ,以后经常会用到。他其实是对C++中的Map进行的一个封装,键的类型被限定为了’e’,’v’,’g’,而值可以映射为int,float,vector等多种c++类型,用法如下:
import graph_tool.all as gt g=gt.price_network(200) prop_v=g.new_vertex_property("int")#创建一个节点到int的映射 #prop_e=g.new_edge_property("int")#创建一个边到int的映射 #prop_g=g.new_graph_property("int")#创建一个图到int的映射 prop_v.a=np.ones(g.num_vertices()) #为prop_v赋值 #print prop_v.a#直接获取映射数组 #print prop_v[2]#按下标取值 #print prop_v.value_type()#值的类型 #print prop_v.key_type()#键的类型
我们也可以直接把PropertyMap跟Graph绑定:
g.properties[("e", "foo")] = g.new_edge_property("vector<double>") g.vertex_properties["foo"] = g.new_vertex_property("double") g.vertex_properties["bar"] = g.new_vertex_property("python::object") g.graph_properties["gnat"] = g.new_graph_property("string", "hi there!")
绘图方法
我的目的是画图,那么我就重点研究了下用来画”图”的函数graph_draw。这个函数必选参数只有一个,但是可选参数却有十几个,我们选几个重要的一一讨论。
下面是函数原型:
graph_tool.draw.graph_draw(g, pos=None, vprops=None, eprops=None, vorder=None, eorder=None, nodesfirst=False, output_size=(600, 600), fit_view=True, inline=False, mplfig=None, output=None, fmt='auto', **kwargs)
必备参数
必备的参数肯定是g,是指我们需要画的Graph对象。
pos参数
pos参数是指我们通过一些布局算法计算出来的对于每一个节点的坐标,是一个PropertyMap对象。这个PropertyMap对象其实就是一个映射,每一个节点的下标对应了该节点的x,y坐标。这个对象是通过布局算法生成的就行了。默认情况下我们用的是 sfdp_layout()
方法来生成这一系列坐标。
vorder,eorder,nodefirst参数
这些参数控制的是绘图的顺序,主要是考虑了一些点线的覆盖问题。
output参数
这个参数指定的是文件的输出文件名和格式,可以根据后缀判断,支持png,svg,pdf,ps四种文件格式。当然也可以用fmt参数直接指定格式。通常情况下png方便显示,但是容易失真。pdf和svg是基于矢量的,放大不失真。
有趣的是如果不指定这个参数,那么他会生成一个可以交互的界面:
这个界面至少有下面的功能:
- 点击一个节点,左下角会显示这个节点的下标
- 点击一个节点,他会高亮与之相邻的节点
- 我们可以对图片进行放大,缩小,旋转
- 我们可以拖动节点从而改变图的形状
- 对图片进行修改后,在我们关闭界面之后,修改后的布局会被更新到pos参数里
vertex_*,edge_*
属性
这些属性可以指定具体画图的样式,样式表可以参见 文档 ,下面用几个例子说明。
import graph_tool.all as gt import numpy as np g = gt.price_network(1500) deg = g.degree_property_map("in") deg.a = 4 * (np.sqrt(deg.a) * 0.5 + 0.4) ebet = gt.betweenness(g)[1] ebet.a /= ebet.a.max() / 10. eorder = ebet.copy() eorder.a *= -1 pos = gt.sfdp_layout(g) gt.graph_draw(g, pos=pos, vertex_size=deg, vertex_fill_color=deg, vorder=deg,edge_color=ebet, eorder=eorder, edge_pen_width=ebet, output="output.png")
这个例子非常简单而且经典,他做了下面的事情:
- 随机初始化了一个由5000个节点组成的price_network模型
- 用PropertyMap deg保存所有节点的入度,用于保存节点的权重
- 对deg的值做了个简单的函数变换
- 用PropertyMap ebet保存所有边的betweenness中心度,用于保存边的权重
- 将ebet的值归一化到0-10之间
- 用PropertyMap eorder对ebet进行拷贝并取反,用于保存绘图顺序
- 用PropertyMap pos保存sfdp算法生成的图的坐标信息
- 将节点的大小、颜色用deg控制,将边的粗细、颜色用ebet控制,随后输出成png。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 利用 t-SNE 降维并可视化数据
- 利用 Python 中 Bokeh 实现数据可视化,第二部分:交互
- 利用Python网络爬虫抓取微信好友的签名及其可视化展示
- [译] 利用 Python 中的 Bokeh 实现数据可视化,第一部分:入门
- 【译】利用 Python中的 Bokeh 实现数据可视化,第三部分:制作一个完整的仪表盘
- 微博 Qzone 微信 利用Python网络爬虫抓取微信好友的所在省位和城市分布及其可视化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Inside Larry's and Sergey's Brain
Richard Brandt / Portfolio / 17 Sep 2009 / USD 24.95
You’ve used their products. You’ve heard about their skyrocketing wealth and “don’t be evil” business motto. But how much do you really know about Google’s founders, Larry Page and Sergey Brin? Inside......一起来看看 《Inside Larry's and Sergey's Brain》 这本书的介绍吧!