1 Graphviz 几何图形工具
Graphviz 是一个几何图形可视化软件,能够将数据的结构信息表示为抽象图形和网络图的方式。PyGraphviz 主要对数据量大、可任意定制的图形上具有强大优势。
建议:由于 PyGraphviz 暂时无法对同源节点合并线段。在流程图、小型结构图方面,Visio 可以作为 Graphviz 的直接替代软件。
2 获取模块
(1) Windows 系统
步骤一:到官网 Graphviz 官网下载 msi 文件,并将 Graphviz2.38\bin 添加到环境变量;
步骤二:终端输入pip install graphviz
(2) MacOS 系统
步骤一:在终端使用 Homebrew 下载: brew install graphviz
步骤二:终端输入pip install graphviz
3 快速入门
(1) 导入模块
import pygraphviz as pgv
(2) 创建图形
G = pgv.AGraph(directed=True, strict=False, nodesep=0, ranksep=1.2, rankdir="TB",
splines="none", concentrate=True, bgcolor="write",
compound=True, normalize=False, encoding='UTF-8')directed -> False | True:有向图
strict -> True | False:简单图
nodesep:同级节点最小间距
ranksep:不同级节点最小间距
rankdir:绘图方向,可选 TB (从上到下), LR (从左到右), BT (从下到上), RL (从右到左)
splines:线条类型,可选 ortho (直角), polyline (折线), spline (曲线), line (线条), none (无)
concentrate -> True | False:合并线条 (双向箭头)
bgcolor:背景颜色
compound -> True | False:多子图时,不允许子图相互覆盖
normalize -> False | True:以第一个节点作为顶节点
(3) 添加节点
G.add_node(name, label=None, fontname="Times-Roman", fontsize=14,
shape="ellipse", style="rounded", color="black", fontcolor="black",
pos="x,y(!)", fixedsize=False, width=1, height=1)
G.add_nodes_from(names, **attr) # 批量添加点,参数同上name -> str:节点名。label 为节点标签,未指定时显示 name
fontname:字体名称,常用:Microsoft YaHei, SimHei, KaiTi, SimSun, FangSong, Times-Roman, Helvetica, Courier。可以使用 "times bold italic" 表示字体类型、粗细、倾斜
fixedsize -> Flase | True | "shape"`:固定大小,默认随文本长度变化。设置为 True 时,width 和 height 参数共同控制点大小。设置为 "shape" 时,将取标签文本和设置值的较大者
style:节点线样式,使用 `color` 设置线条颜色 (style="filled" 时,设置填充颜色)shape:节点形状pos -> str:点的初始位置。使用 "x,y!" 时,可以强制固定点的位置。
(4) 添加边
G.add_edge(origin, target, color="black", style="solid", penwidth=1,
label="", fontname="Times-Roman", fontsize=14, fontcolor="black",
arrowsize=1, arrowhead="normal", arrowtail="normal", dir="forward")
G.add_nodes_from([[origin_1, target_1],
[origin_2, target_2],...], **attr) # 批量添加线,参数同上label -> str:边标签,未指定时不显示
penwidth:线条粗细
arrowsize:箭头大小
arrowhead:箭头类型,可选 normal, vee
dir:箭头方向,可选 both, forward, back, none。只有在无向图中才起作用!
(5) 导出图形
G.layout()
G.draw(file_name, prog="neato")prog:布局算法,可选 neato, dot (推荐), twopi, circo, fdp
4 案例
4.1 案例一:因果关系图
import pygraphviz as pgv
G = pgv.AGraph(directed=True, strict=False, ranksep=0.2, splines="spline", concentrate=True)
# 设置节点标签
nodeA = "Police\nIntelligence"
nodeB = "Police Station"
nodeC = "Criminal Action"
nodeD = "Incidents"
nodeE = "Police Dockets"
nodeF = "Control Room\nAwareness"
nodeG = "Patroller Information"
nodeH = "Patroller Awareness"
# 添加节点
G.add_nodes_from([nodeA, nodeB, nodeC, nodeD, nodeE, nodeF, nodeG, nodeH],
color="#ffffff", fontname="times bold italic")
# 添加边
G.add_edges_from([[nodeA, nodeB], [nodeA, nodeF], [nodeB, nodeC], [nodeC, nodeD],
[nodeC, nodeG], [nodeD, nodeE], [nodeD, nodeG], [nodeE, nodeA],
[nodeF, nodeA], [nodeF, nodeG], [nodeF, nodeH], [nodeG, nodeF],
[nodeH, nodeG]], color="#7F01FF", arrowsize=0.8)
# 导出图形
G.layout()
G.draw("因果关系图.png", prog="dot")
4.2 案例二:因子相关性图
import pygraphviz as pgv
G = pgv.AGraph(directed=True, rankdir="TB")
# 设置节点标签
Root = "道路交通流畅"
negative_1 = "平均延误时间"
negative_2 = "负荷度"
negative_3 = "小区位置"
negative_4 = "相对延误率"
negative_5 = "房屋密度"
negative_6 = "人口密度"
negative_7 = "总延误率"
negative_8 = "排队率"
negative_9 = "行驶时间"
positive_1 = "通行能力"
positive_2 = "公路层级"
positive_3 = "路网结构"
positive_4 = "行驶速度"
positive_5 = "路网长度"
positive_6 = "小区面积"
positive_7 = "内部道路密度"
positive_8 = "路网密度"
# 添加节点
G.add_node(Root, style="filled", shape="box3d", color="#feb64d")
for negative in [eval(_) for _ in dir() if _.startswith("negative")]:
G.add_node(negative, style="filled", shape="ellipse", color="#CFDBF6")
for positive in [eval(_) for _ in dir() if _.startswith("positive")]:
G.add_node(positive, style="filled", shape="ellipse", color="#B4E7B7")
# 添加边
G.add_edges_from([[Root, negative_1], [Root, negative_6], [Root, negative_8], [Root, negative_9],
[negative_1, negative_2], [negative_1, negative_7], [negative_2, negative_3],
[negative_2, negative_7], [negative_3, negative_4], [negative_8, negative_9],
[positive_2, negative_5], [positive_3, negative_4], [positive_4, negative_5]],
color="#B4DBFF", style="dashed", penwidth=1.5)
G.add_edges_from([[Root, positive_1], [Root, positive_8], [negative_5, negative_4],
[negative_6, positive_4], [negative_5, positive_4], [negative_9, positive_5],
[positive_1, positive_2], [positive_2, positive_3], [positive_6, positive_5],
[positive_7, positive_6], [positive_8, positive_7]],
color="#B4E7B7", style="dashed", penwidth=1.5)
# 导出图形
G.layout()
G.draw("因子相关性图.png", prog="dot")
4.3 案例三:简单神经网络图
import pygraphviz as pgv
G = pgv.AGraph(directed=True, rankdir="LR")
# 设置层数、每层节点数
network_structure = input("输入神经网络每层节点数,如:[10, 7, 5, 4, 2, 1]\n")
all_nodes = [[f"layer{layer_index}node{node_index}" for node_index in range(layer_nodes_num)] for
layer_index, layer_nodes_num in enumerate(eval(network_structure))]
# 添加输入层节点
for node_index, node in enumerate(all_nodes[0]):
G.add_node(node, label="", shape="circle", style="bold", color="#60acfc", pos=f"0,{0.6 * node_index}!")
# 添加输入层文本
G.add_node(f"Input_Layer", shape="none", label=f"Input_Layer({len(all_nodes[0])})",
pos=f"{0},{(node_index + 1) * 0.6}!")
# 添加中间层、输出层节点
for layer_index, layer in enumerate(all_nodes[1:]):
color = "#5bc49f" if layer_index == len(all_nodes[1:]) - 1 else "#ff7c7c"
for node_index, node in enumerate(layer):
x = 1.5 * (layer_index + 1)
y = - 0.3 * (len(all_nodes[layer_index + 1]) - len(all_nodes[0])) + 0.6 * node_index
G.add_node(node, label="", shape="circle", style="bold", color=color, pos=f"{x},{y}!")
# 添加中间层、输出层文本
text = f"Output_Layer({len(all_nodes[-1])})" if layer_index == len(all_nodes[1:]) - 1 else f"Layer_{layer_index + 1}({len(layer)})"
G.add_node(f"Layer_{layer_index + 1})", shape="none", label=text,
pos=f"{x},{y + 0.4}!")
# 添加线
for layer_index in range(all_nodes.__len__() - 1):
for start in all_nodes[layer_index]:
for end in all_nodes[layer_index + 1]:
G.add_edge(start, end)
# 导出图形
G.layout()
G.draw("神经网络.png")
# 运行代码,输入 [5, 10, 15, 15, 15, 10, 5, 1]
作者:张柳彬
如有疑问,请联系QQ:965579168
不接论文代做, 转载请声明出处