SPSS视频教程内容目录和跳转链接

python-graphviz图数据可视化入门

微博@mlln-cn, 并附上文章url链接, 我就能回答你的问题奥!

文章目录
  1. 1. 安装
  2. 2. 依赖
  3. 3. 基本用法
  4. 4. 字体乱码
  5. 5. piped输出
  6. 6. jupyter notebook中显示
  7. 7. 显示风格
  8. 8. 属性
  9. 9. 使用引号和HTML作为label
  10. 10. 子图和集群
  11. 11. 引擎
  12. 12. 添加dot语句
  13. 13. 使用dot文件和源码
  14. 14. 使用临时文件浏览图


本文代码运行环境:

  • windows10
  • python3.6
  • jupyter notebook

安装

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()方法将节点和边添加到图形对象:

  • node()方法第一个参数是name, 第二个参数是label
  • edges()方法可以一次添加多个边, 每个边用字符串表示, 比如AB表示从A到B的边
  • edge()方法一次添加一个边
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
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()`方法用于添加子图, 它有两种用法:

  • 可以直接添加一个Graph或者Bigraph对象:
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

  • 使用with代码块:
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

使用临时文件浏览图

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

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
有问题可以直接在下方留言
或者给我发邮件675495787[at]qq.com
请记住我的网址: mlln.cn 或者 jupyter.cn

赞助

持续创造有价值的内容, 我需要你的帮助