利用graphtool进行图的可视化处理

栏目: C++ · 发布时间: 7年前

内容简介:利用graphtool进行图的可视化处理

最近恶心的项目中期检查,我被分配到做社交图的分析,然而事实上我并不知道弄啥。虽然不是我自己答辩,但是考虑到还是不要太坑dalao,我决定不管怎样至少得搞点图撑撑场面免得尴尬,这几天就赶鸭子上架倒腾了下 graph_tool 这个专门用于对图进行可视化的 python 库。虽然网上中文资料不足,但是他的英文文档还是非常全面的,很多设计的小细节也在文档里提及了,非常简单容易上手。下面就从一个初学者的记录下我的学习历程。

安装

虽然是个python库,但是毕竟是要做大量数据计算的,因此graphtool在底层使用了Boost, CGAL 和 expat这几个C++库(Boost是扩展的标准库,CGAL是一个计算几何算法库,expat是一个XML解析器)。这就导致了使用通常的pip和easyinstall不太好直接安装。正确的安装姿势大概有三种:

  1. 使用Docker
  2. 源码安装
  3. 各个 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是基于矢量的,放大不失真。

有趣的是如果不指定这个参数,那么他会生成一个可以交互的界面:

利用graphtool进行图的可视化处理 这个界面至少有下面的功能:

  • 点击一个节点,左下角会显示这个节点的下标
  • 点击一个节点,他会高亮与之相邻的节点
  • 我们可以对图片进行放大,缩小,旋转
  • 我们可以拖动节点从而改变图的形状
  • 对图片进行修改后,在我们关闭界面之后,修改后的布局会被更新到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")

这个例子非常简单而且经典,他做了下面的事情:

  1. 随机初始化了一个由5000个节点组成的price_network模型
  2. 用PropertyMap deg保存所有节点的入度,用于保存节点的权重
  3. 对deg的值做了个简单的函数变换
  4. 用PropertyMap ebet保存所有边的betweenness中心度,用于保存边的权重
  5. 将ebet的值归一化到0-10之间
  6. 用PropertyMap eorder对ebet进行拷贝并取反,用于保存绘图顺序
  7. 用PropertyMap pos保存sfdp算法生成的图的坐标信息
  8. 将节点的大小、颜色用deg控制,将边的粗细、颜色用ebet控制,随后输出成png。

利用graphtool进行图的可视化处理


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深度探索C++对象模型

深度探索C++对象模型

斯坦利•B.李普曼 (Stanley B. Lippman) / 侯捷 / 电子工业出版社 / 2012-1 / 69.00元

作者Lippman参与设计了全世界第一套C++编译程序cfront,这本书就是一位伟大的C++编译程序设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码中)和implicit(隐藏于程序代码背后)的C++语意。 本书专注于C++面向对象程序设计的底层机制,包括结构式语意、临时性对象的生成、封装、继承,以及虚拟——虚拟函数和虚拟继承。这本书让你知道:一旦你能够了解底层实现模......一起来看看 《深度探索C++对象模型》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具