用Python调用Graphviz生成复杂股权关系图

一、为啥用Graphviz?

最近接触一个项目需要根据数据自动生成持股关系较为复杂的股权关系图,之所以说复杂主要体现在股权层级多,还有一些特殊持股方式,比如一个子公司在集团内有多家公司持股,还有相互持股等情况,这些情况用Visio等常规手动绘图工具就不好用了。
Graphviz (Graph Visualization Software) 是一个由AT&T实验室启动的开源工具。她使用DOT语言来描述图形的节点、连线及属性等,可以大大减少手绘图形调整图形格式的时间,而将主要精力放在图形的逻辑关系上。而且可以根据需要设置生成图像的格式,如PDF、JPG等。
用Python调用主要因为可以方便地进行迭代等数据处理,从而实现根据数据自动生成图像。

二、在Python中安装Graphviz库

pip install graphviz

三、安装并配置Graphviz

光是在Python中安装了Graphviz库还不能画图,必须要安装Graphviz这个工具并在Windows系统中把bin文件夹的路径加入到环境变量path里。
1、Graphviz官网安装包(msi)地址:https://graphviz.gitlab.io/_pages/Download/Download_windows.html
2、关于如何配置环境变量可以参考这篇文章:
https://zhuanlan.zhihu.com/p/35639711

四、DOT语法

Python中调用DOT语法比较简单,可以参考:
1、官方文档(英文):
https://graphviz.readthedocs.io/en/stable/manual.html
2、一些节点、连线的字体、形状、颜色等属性参数的设置可以参考这篇文章:
python graphviz的使用(画图工具)https://blog.csdn.net/weixin_30314813/article/details/101197728

五、代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from graphviz import Digraph
#下面L中为需要填写的数据,字段分别为“序号”、“父单位”、“父单位层级”、“子单位”、“子单位层级”、“父单位持股比例 ”,可以填在excel中后,用百度的Echarts表格工具转换为该格式
L=[
    [1, 'A公司', 1, 'B1公司', 2, '70.00%'],
    [2, 'A公司', 1, 'B2公司', 2, '50.00%'],
    [3, 'A公司', 1, 'B3公司', 2, '40.00%'],
    [4, 'B1公司', 2, 'C1公司', 3, '10.00%'],
    [5, 'B1公司', 2, 'C2公司', 3, '20.00%'],
    [6, 'B1公司', 2, 'C3公司', 3, '30.00%'],
    [7, 'B2公司', 2, 'C3公司', 3, '40.00%'],
    [8, 'B2公司', 2, 'C4公司', 3, '35.00%'],
    [9, 'B3公司', 2, 'C4公司', 3, '20.00%'],
    [10, 'B3公司', 2, 'C5公司', 3, '30.00%'],
    [11, 'C4公司', 3, 'C5公司', 3, '30.00%'],
    [12, 'C5公司', 3, 'B1公司', 2, '10.00%']
]
dic={}
father_name_list=[]
child_name_list=[]
equity_portion_list=[]
for i1 in range(len(L)):
    M=L[i1]
    father_name=M[1]
    father_name_list.append(M[1])
    father_layer=M[2]
    child_name=M[3]
    child_name_list.append(M[3])
    child_layer=M[4]
    equity_portion=M[5]
    equity_portion_list.append(M[5])
    for x in father_name:
        dic[father_name]=father_layer   #生成父单位名称和对应的层级(用字典考虑去重)
    for y in child_name:
        dic[child_name]=child_layer     #将子单位名称和对应的层级也添加到字典中

name_layer_list = sorted(dic.items(), key=lambda x: x[1]) #对字典按值(value)进行排序(默认由小到大)

u=[]
for z in name_layer_list:
    company_name=z[0]
    layer=z[1]
    u.append(z[1])
number_of_layers=max(u) #计算出层数

#按各公司的层数生产分层的节点:
g=Digraph(name='复杂股权结构图')

for key in dic:
    for n in range(number_of_layers+1):
        if dic[key]==n:
            with g.subgraph() as layer_n:
                layer_n.attr(rank='same')
                layer_n.node(name=key,color='blue',shape='box',fontname='Microsoft YaHei')

#生产各节点间的连线:
for i2 in range(len(L)):
    g.edge(father_name_list[i2],child_name_list[i2],label=equity_portion_list[i2],color='red',fontname='Microsoft Yahei')

g.view()  

六、操作步骤

代码中需要的数据L可以按以下模板在Excel中填好后,用百度的Echarts表格工具转换为JavaScript格式(偷个懒,没有写Python调用Excel的模块)。
1、先按如下Excel模板填入股权数据:
在这里插入图片描述
2、再用百度Echarts的表格工具装换成JavaScript格式后替代代码中的L部分:
在这里插入图片描述
3、运行代码

七、结果

运行代码后自动生成如下PDF、JPG等图像:
在这里插入图片描述

八、待优化事项

节点之间生成的连线有些为曲线,在公司较多时不太美观,用折线要好看些。如果不用Python调用,直接用Graphviz画才能将图属性设置为splines=“line"或者"ortho”(强制边缘是直的,没有曲线或角度折线),但是Python的Graphviz貌似没有这个属性可以设置,我还要再研究研究。
Graphviz官方文档:http://graphviz.org/doc/info/attrs.html

  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值