python-graphviz图数据可视化入门

xxxspy 2018-09-25 20:17:55
Categories: Tags:

本文代码运行环境:

安装

graphviz为Graphviz图形绘制软件提供了一个简单的纯Python接口。它在Python 2.7和3.4+下运行。要使用pip安装它,请运行以下命令:

1
pip install graphviz

依赖

graphviz有一个同名依赖graphviz, 这是一个c开发的软件包, 可以通过命令行调用。它的安装很简单, 如果在windows下, 只需要下载二进制包进行安装即可, 具体过程参考这篇文章的安装Graphviz部分。

基本用法

graphviz模块提供两个类:GraphDigraph。他们使用DOT语言为无向和有向图创建图形描述。他们有相同的API。

通过实例化新的Graph或Digraph对象来创建图形:

1
2
3
from graphviz import Digraph
dot = Digraph(comment='这是一个有向图')
str(dot)
输出(plain):
'// 这是一个有向图\ndigraph {\n}'

它们的构造函数允许设置图形的name,DOT代码的filename,源代码行的注释等。

使用node()edge()edges()方法将节点和边添加到图形对象:

1
2
3
4
5
6
7
8
dot = Digraph(comment='这是一个有向图')
dot.node('A', '作者')
dot.node('B', '医生')
dot.node('C', '律师')

dot.edges(['AB', 'AC'])
dot.edge('B', 'C')
print(dot.source)
输出(stream):
// 这是一个有向图
digraph {
A [label="作者"]
B [label="医生"]
C [label="律师"]
A -> B
A -> C
B -> C
}

使用render方法将保存dot源码, 并且会渲染图形, 使用view=True参数可以自动打开应用程序以便浏览生成的图:

1
2
3
# 将dot源码保存到文件:output-graph.gv
# 同时会生成一个pdf文件: output-graph.gv.pdf
dot.render('output-graph.gv', view=True)
输出(plain):
'output-graph.gv.pdf'

除了PDF, 还可以生成其他格式, 比如png:

1
2
dot.format = 'png'
dot.render('output-graph.gv', view=True)
输出(plain):
'output-graph.gv.png'

由于这是jupyter notebook环境, 我们直接使用notebook展示生成的图片即可:

1
2
from IPython.display import display, Image
Image(dot.render('output-graph.gv'))

png

字体乱码

我们可以看到中文的label无法正确显示在图中, 因为默认的字体并不支持中文, 需要我们为node设置字体, 比如我们设置成黑体:

1
2
3
4
5
6
7
8
9
dot = Digraph(comment='这是一个有向图')
dot.node('A', '作者', fontname="Heiti")
dot.node('B', '医生')
dot.node('C', '律师')
dot.edges(['AB', 'AC'])
dot.edge('B', 'C')
dot.format = 'png'
Image(dot.render('output-graph-font.gv'))

输出(stream):

(dot.exe:10280): Pango-WARNING **: couldn't load font "Heiti Not-Rotated 14", falling back to "Sans Not-Rotated 14", expect ugly output.

png

piped输出

为了直接获取Graphviz软件渲染结果, 而不是让它保存到文件中, 我们可以使用pipe()方法, 比如我们可以直接获取渲染后的svg源码:

1
2
3
4
from graphviz import Graph
h = Graph('hello', format='svg')
h.edge('Hello', 'World')
print(h.pipe().decode('utf-8'))
输出(stream):

"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">


viewBox="0.00 0.00 76.89 116.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

hello


Hello

Hello


World

World


Hello--World





jupyter notebook中显示

因为Graph和Bigraph类都有_repr_svg_()方法, 因此他们可以直接显示在notebook中, 而不需要做任何处理, 例如, 上面的svg图, 可以直接显示:

1
h

svg

显示风格

使用graph_attr, node_attr, edge_attr参数, 你可以更改图中节点和边的显示样式:

1
2
3
4
5
ps = Digraph(name='pet-shop', node_attr={'shape': 'plaintext'})
ps.node('parrot')
ps.node('dead')
ps.edge('parrot', 'dead')
ps

svg

创建完毕以后, 你可以更改这些样式:

1
2
3
ps.graph_attr['rankdir'] = 'LR'
ps.edge_attr.update(arrowhead='vee', arrowsize='2')
ps

svg

属性

我们可以直接更改图中所有节点和边的属性, 相当于全局配置, 只要使用attr方法即可:

1
2
3
4
5
6
7
8
9
ni = Graph('ni')
# 设置所有节点的形状
ni.attr('node', shape='rarrow')
ni.node('1', 'Ni!')
ni.node('2', 'Ni!')
# 如果单独设置, 优先级更高
ni.node('3', 'Ni!', shape='egg')
ni.node('4', 'Ni!')
ni

svg

使用引号和HTML作为label

在label中使用引号需要使用转义字符\:

1
2
ni.node('5', '\"Ni\"')
ni

svg

在label中使用html可以使用< >将html内容括起来, 比如, 我们可以使用下标sub:

1
2
ni.node('6', '<N<sub>i</sub>>')
ni

svg

子图和集群

GraphBigraph'对象都有subgraph()`方法用于添加子图, 它有两种用法:

1
2
3
4
5
6
7
8
p = Graph(name='parent')
p.edge('spam', 'eggs')

c = Graph(name='child', node_attr={'shape': 'box'})
c.edge('foo', 'bar')

p.subgraph(c)
p

svg

1
2
3
4
5
6
p = Graph(name='parent')
p.edge('spam', 'eggs')

with p.subgraph(name='child', node_attr={'shape': 'box'}) as c:
c.edge('foo', 'bar')
p

svg

引擎

渲染引擎可以选择多种, 而不仅仅是dot, 比如你可以使用neato:

1
g = Graph(engine='neato')

或者也可以直接更改渲染引擎:

1
g.engine = 'circo'

添加dot语句

有些应用场景是需要使用已经写好的dot语句的, 这时候我们可以直接调用body.append方法来追加dot语句:

1
2
3
4
rt = Digraph()
rt.body.append('\t"King Arthur" -> {\n\t\t"Sir Bedevere", "Sir Lancelot"\n\t}')
rt.edge('Sir Bedevere', 'Sir Lancelot', constraint='false')
rt

svg

使用dot文件和源码

我们可以直接使用Source类来直接实例化一个Source对象, 传入的参数就是dot源码, 然后可以调用render方法渲染成图片:

1
2
3
from graphviz import Source
src = Source('digraph "the holy hand grenade" { rankdir=LR; 1 -> 2 -> 3 -> lob }')
str(src)
输出(plain):
''

我们还可以直接使用from_file方法来从一个dot文件实例化:

1
2
src = Source.from_file('output-graph-font.gv')
src
输出(stream):

(dot.exe:14100): Pango-WARNING **: couldn't load font "Heiti Not-Rotated 14", falling back to "Sans Not-Rotated 14", expect ugly output.

svg

统计咨询请加QQ 2726725926, 微信 mllncn, SPSS统计咨询是收费的

很多时候我们要多次浏览绘制的图, 但是又不想保存这个文件, 那么我们可以使用临时文件保存生成的结果:

1
2
3
4
5
6
import tempfile

g = Graph()
g.node('spam')

g.view(tempfile.mktemp('.gv'))
输出(plain):
'C:\\Users\\syd\\AppData\\Local\\Temp\\tmp48i7e5z2.gv.pdf'

注意
本文由jupyter notebook转换而来, 您可以在这里下载notebook
有问题可以直接在下方留言
微博上@mlln-cn可以向我免费题问
请记住我的网址: mlln.cn 或者 jupyter.cn