使用Python,maplotlib绘制树型有向层级结构图

使用Python,maplotlib绘制树型有向层级结构图

  • 1. 效果图
  • 2. 源码
    • 2.1 plotTree.py绘制层级结构及不同样式
    • 2.2 plotArrow.py 支持的所有箭头样式
  • 参考

前俩篇博客介绍了
1. 使用Python,networkx对卡勒德胡赛尼三部曲之《群山回唱》人物关系图谱绘制
2. 使用Python,networkx绘制有向层级结构图
3. 使用Python,maplotlib绘制树型有向层级结构图 这篇博客是绘制层级结构图三部曲最后一篇。

1. 效果图

按父子层级结构绘制图形,并标记之间的关联关系,并根据不同标签绘制不同颜色箭头(hello的蓝色箭头,bad的红色箭头,默认绿色箭头),效果图如下:
在这里插入图片描述

同样是表达层级结构关系,可以很明显的看出来这比上篇博客使用networkx绘制的层级图要清楚很多,一目了然。
在这里插入图片描述

不同箭头样式:
在这里插入图片描述

支持的所有箭头及箭头弯曲程度样式如下:
在这里插入图片描述

2. 源码

2.1 plotTree.py绘制层级结构及不同样式

# python plotTree.py
# 绘制层级结构图,并根据标签值对树绘制不同颜色import matplotlib.pyplot as pltplt.rcParams['backend'] = 'TkAgg'
decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")def getNumLeafs(myTree):numLeafs = 0firstStr = list(myTree.keys())[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':  # test to see if the nodes are dictonaires, if not they are leaf nodesnumLeafs += getNumLeafs(secondDict[key])else:numLeafs += 1return numLeafsdef getTreeDepth(myTree):maxDepth = 0firstStr = list(myTree.keys())[0]secondDict = myTree[firstStr]for key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':  # test to see if the nodes are dictonaires, if not they are leaf nodesthisDepth = 1 + getTreeDepth(secondDict[key])else:thisDepth = 1if thisDepth > maxDepth: maxDepth = thisDepthreturn maxDepthdef plotNode(nodeTxt, centerPt, parentPt, nodeType, color):# 分别表示箭头的样式,俩边距离边框的值,以及箭头线的弯曲程度,箭头的颜色arrow_args = dict(arrowstyle="<-", shrinkA=10, shrinkB=10, patchA=None, patchB=None, connectionstyle="arc3,rad=0.3",color=color)arrow_args = dict(arrowstyle="<-", shrinkA=10, shrinkB=10, patchA=None, patchB=None, connectionstyle="arc3, rad = 0.",color=color)createPlot.ax1.annotate(nodeTxt, xy=parentPt, xycoords='axes fraction',xytext=centerPt, textcoords='axes fraction',va="center", ha="center", bbox=nodeType, arrowprops=arrow_args)def plotMidText(cntrPt, parentPt, txtString):xMid = (parentPt[0] - cntrPt[0]) / 2.0 + cntrPt[0]yMid = (parentPt[1] - cntrPt[1]) / 2.0 + cntrPt[1]createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)def getArrowColors(parentNode, firstStr, edgeDict):key = parentNode + '->' + firstStrif not edgeDict.__contains__(key):color = 'black'elif edgeDict[key].__contains__('hello'):color = 'blue'elif edgeDict[key].__contains__('bad'):color = 'red'else:color = 'green'return colordef getArrowAttrTxt(parentNode, firstStr, edgeDict):key = parentNode + '->' + firstStrif not edgeDict.__contains__(key):return ''return edgeDict[key]def plotTree(myTree, parentPt, parentNode, nodeTxt):numLeafs = getNumLeafs(myTree)depth = getTreeDepth(myTree)firstStr = list(myTree.keys())[0]cntrPt = (plotTree.xOff + (1.0 + float(numLeafs)) / 2.0 / plotTree.totalW, plotTree.yOff)plotMidText(cntrPt, parentPt, getArrowAttrTxt(parentNode, firstStr, edgeDict))plotNode(firstStr, cntrPt, parentPt, decisionNode, getArrowColors(parentNode, firstStr, edgeDict))secondDict = myTree[firstStr]plotTree.yOff = plotTree.yOff - 1.0 / plotTree.totalDfor key in secondDict.keys():if type(secondDict[key]).__name__ == 'dict':print("++++++++++++: ", key, firstStr)plotTree(secondDict[key], cntrPt, firstStr, str(key))  # recursionelse:print('----: ', secondDict[key], firstStr, key)plotTree.xOff = plotTree.xOff + 1.0 / plotTree.totalWplotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode,getArrowColors(firstStr, secondDict[key], edgeDict))plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, getArrowAttrTxt(firstStr, secondDict[key], edgeDict))plotTree.yOff = plotTree.yOff + 1.0 / plotTree.totalDdef createPlot(inTree):fig = plt.figure(1, facecolor='white')fig.clf()axprops = dict(xticks=[], yticks=[])createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)  # no ticks# createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropsesplotTree.totalW = float(getNumLeafs(inTree))plotTree.totalD = float(getTreeDepth(inTree))plotTree.xOff = -0.5 / plotTree.totalW;plotTree.yOff = 1.0;plotTree(inTree, (0.5, 1.0), 'A', '')plt.show()def retrieveTree(i):listOfTrees = [{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},{'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}]return listOfTrees[i]def getTree(treeDict, nood):retrieveTree = {}for i, val in enumerate(treeDict[nood]):print(i, nood, val)if (treeDict.__contains__(val)):subTree = {}subTree[val] = getTree(treeDict, val)retrieveTree[i] = subTreeelse:retrieveTree[i] = valreturn retrieveTreedef getRetrieveTree():treeDict = {}edgeDict = {}with open("res/tree.txt", 'r', encoding='utf-8', errors='ignore') as f:data = f.readlines()for i, line in enumerate(data):parentNode = line.split(",")[0]childNode = line.split(",")[1]edgeDict[parentNode + "->" + childNode] = line.split(",")[2]# print(parentNode, childNode)if not treeDict.__contains__(parentNode):treeDict[parentNode] = set()treeDict[parentNode].add(childNode)print(treeDict)treeDict0 = {}treeDict0['A'] = getTree(treeDict, 'A')# print(treeDict0)return (treeDict0, edgeDict)# treeDemo = retrieveTree(1)
# print(treeDemo)
# createPlot(treeDemo)
(treeDict, edgeDict) = getRetrieveTree()
print(treeDict)
createPlot(treeDict)

2.2 plotArrow.py 支持的所有箭头样式

# python plotArrow.py
from matplotlib import pyplot as pltprint(plt.rcParams['backend'])  # module://backend_interagg
plt.rcParams['backend'] = 'TkAgg'def demo_con_style(ax, connectionstyle):x1, y1 = 0.3, 0.2x2, y2 = 0.8, 0.6ax.plot([x1, x2], [y1, y2], ".")ax.annotate("", xy=(x1, y1), xycoords='data',xytext=(x2, y2), textcoords='data',arrowprops=dict(arrowstyle="->", color="0.5",shrinkA=5, shrinkB=5,patchA=None, patchB=None,connectionstyle=connectionstyle,),)ax.text(.05, .95, connectionstyle.replace(",", ",\n"),transform=ax.transAxes, ha="left", va="top")fig, axs = plt.subplots(3, 5, figsize=(8, 4.8))
demo_con_style(axs[0, 0], "angle3, angleA = 90, angleB = 0")
demo_con_style(axs[1, 0], "angle3, angleA = 0, angleB = 90")
demo_con_style(axs[0, 1], "arc3, rad = 0.")
demo_con_style(axs[1, 1], "arc3, rad = 0.3")
demo_con_style(axs[2, 1], "arc3, rad = -0.3")
demo_con_style(axs[0, 2], "angle, angleA = -90, angleB = 180, rad = 0")
demo_con_style(axs[1, 2], "angle, angleA = -90, angleB = 180, rad = 5")
demo_con_style(axs[2, 2], "angle, angleA = -90, angleB = 10, rad = 5")
demo_con_style(axs[0, 3], "arc, angleA = -90, angleB = 0, armA = 30, armB = 30, rad = 0")
demo_con_style(axs[1, 3], "arc, angleA = -90, angleB = 0, armA = 30, armB = 30, rad = 5")
demo_con_style(axs[2, 3], "arc, angleA = -90, angleB = 0, armA = 0, armB = 40, rad = 0")
demo_con_style(axs[0, 4], "bar, fraction = 0.3")
demo_con_style(axs[1, 4], "bar, fraction = -0.3")
demo_con_style(axs[2, 4], "bar, angle = 180, fraction = -0.2")for ax in axs.flat:ax.set(xlim=(0, 1), ylim=(0, 1), xticks=[], yticks=[], aspect=1)
fig.tight_layout(pad=0.2)plt.show()

参考

  • https://blog.csdn.net/weixin_42915773/article/details/111566041
  • https://blog.csdn.net/TQCAI666/article/details/103689182

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/266332.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 学习第四弹——字符串

一、char类型的使用 字符使用单引号&#xff0c;单个字符 转义字符是一种特殊的字符变量&#xff0c;以反斜线开头&#xff0c;后跟一个或多个字符。 输出多级目录可以使用 二、字符串的声明和初始化 1、引用字符串常量 引用字符串常量初始化——字符使用单引号&#xff0…

阿里云轻量服务器,ubuntu20.04安装Redis

第一步&#xff1a;下载xshell7,连接阿里云服务器 就是下图这个ip 第二步&#xff1a;输入用户名和密码 上面那一步完成之后&#xff0c;就会弹出来下面这个图片 用户名是root 密码是你的阿里云服务器密码 如果你要是忘了&#xff0c;如下图&#xff0c;重置密码&#xff0…

【Redis:事务】

1 &#x1f351;事务概念&#x1f351; Redis 的事务和 MySQL 的事务概念上是类似的&#xff0c;都是把⼀系列操作绑定成⼀组&#xff0c;让这⼀组能够批量执⾏。 但是注意体会 Redis 的事务和 MySQL 事务的区别: 弱化的原⼦性: redis 没有 “回滚机制”. 只能做到这些操作 “…

unity后期

unity|后处理篇 前言一、Post-Processing 1、 Post-Processing的使用2、Post-Processing后处理效果 抗锯齿①、Ambient Occlusion 环境光遮蔽②、Auto Exposure 自动曝光③、Bloom 辉光/泛光④、Chromatic Aberration | 色差⑤、Color Grading 色调/颜色分级⑥、Depth Of Fiel…

数据卷dockerfile

目录 一、数据卷 1. 简介 2. 数据卷和数据卷容器 1. 数据卷&#xff1a; 2. 数据卷容器&#xff1a; 二、自定义镜像 1. 作用 2. 自定义centos 3. 自定义tomcat8 一、数据卷 1. 简介 数据卷是一个可供一个或多个容器使用的特殊目录&#xff0c;它将主机操作系统目录直…

【Python笔记-设计模式】状态模式

一、说明 状态模式是一种行为设计模式&#xff0c;用于解决对象在不同状态下具有不同行为 (一) 解决问题 在对象行为根据对象状态而改变时&#xff0c;规避使用大量的条件语句来判断对象的状态&#xff0c;提高系统可维护性 (二) 使用场景 当对象的行为取决于其状态&#…

List集合的Stream流式操作实现数据类型转换

问题现象&#xff1a; 最近在项目中&#xff0c;有一些逻辑想用List集合的Stream流式操作来快速实现&#xff0c;但由于之前没做好学习笔记和总结&#xff0c;导致一时间想不起来&#xff0c;只能用本方法来解决&#xff0c;如下&#xff1a; 可以看出来代码量是比较冗长的&…

智能驾驶规划控制理论学习-基于采样的规划方法

目录 一、基于采样的规划方法概述 二、概率路图&#xff08;PRM&#xff09; 1、核心思想 2、实现流程 3、算法描述 4、节点连接处理 5、总结 三、快速搜索随机树&#xff08;RRT&#xff09; 1、核心思想 2、实现流程 3、总结 4、改进RRT算法 ①快速搜索随机图&a…

postman切换成黑色主题

postman安装以后默认是白色背景&#xff0c;如果想要切换成黑色的&#xff0c;大家可以按照下图箭头指示来操作。 1打开设置 2在Themes页面选择黑色主题

4G 蜂窝移动通信系统

4G 蜂窝移动通信系统 第四代 (4G) 蜂窝移动通信系统 2008 年&#xff0c;名称定为高级国际移动通信 IMT-Advanced (International Mobile Telecommunications-Advanced) 。 IMT-Advanced 的一个最重要的特点&#xff1a;取消了电路交换&#xff0c;无论传送数据还是话音&#…

从 iOS 设备恢复数据的 20 个iOS 数据恢复工具

作为 iPhone、iPad 或 iPod 用户&#xff0c;您可能普遍担心自己可能会丢失存储在珍贵 iOS 设备中的所有宝贵数据。数据丢失的原因多种多样&#xff0c;这里列出了一些常见原因&#xff1a; 1. iOS 软件更新 2. 恢复出厂设置 3. 越狱 4. 误操作删除数据 5. iOS 设备崩溃 …

易货模式微信小程序的可行性分析

随着移动互联网技术的快速发展&#xff0c;微信小程序作为一种轻量级的应用形态&#xff0c;已经成为众多创业者和服务提供者关注的焦点。微信小程序以其便捷的使用体验、较低的开发成本和广泛的用户基础&#xff0c;成为了各类业务模式的创新平台。在这样的背景下&#xff0c;…

c# ABB 机械手上位机连接

c# 程式开发和调试步骤如下&#xff1a; ABB 机械手要开启PC Interface功能。ABB 机械手设定ip地址。设定测试笔记本和机械手同一网段&#xff0c;用网线直连机械手&#xff0c;也可以通过交换机连接机械手。确保笔记本能够ping通和telnet 机械手80端口都是OK的。以上都OK的话…

图神经网络实战——图论

图神经网络实战——图论 0. 前言1. 图属性1.1 有向图和无向图1.2 加权图与非加权图1.3 连通图非连通图1.4 其它图类型 2. 图概念2.1 基本对象2.2 图的度量指标2.2 邻接矩阵表示法 3. 图算法3.1 广度优先搜索3.2 深度优先搜索 小结系列链接 0. 前言 图论 (Graph theory) 是数学…

ifort 自定义命名可执行程序

背景 在Linux上用ifort编译Fortran程序时&#xff0c;想自定义可执行程序的名字 有帖子&#xff08;ifort编译命令&#xff09;说可以使用这个&#xff1a; ifort -c 自定义命名 ***.f90 亲测不行 步骤 ifort ***.f90 &#xff1a; 默认产生的是a.out可执行程序 亲测有效&…

内网穿透 nas/树莓派+ipv4服务器 (ipv6)

nas 1.有个服务器 2.有个nas https://github.com/snail007/goproxy/blob/master/README_ZH.md https://github.com/snail007/proxy_admin_free/blob/master/README_ZH.md 2个官网一个是程序&#xff0c;一个是网站 手册 https://snail007.host900.com/goproxy/manual/zh/#/?i…

KubeEdge 边缘计算

文章目录 1.KubeEdge2.KubeEdge 特点3.KubeEdge 组成4.KubeEdge 架构 KubeEdge # KubeEdgehttps://iothub.org.cn/docs/kubeedge/ https://iothub.org.cn/docs/kubeedge/kubeedge-summary/1.KubeEdge KubeEdge 是一个开源的系统&#xff0c;可将本机容器化应用编排和管理扩展…

「MySQL」增删查改

在操作数据库中的表时&#xff0c;需要先使用该数据库&#xff1a; use database;新增 创建表 先用 use 指定一个数据库,然后使用 create 新增一个表 比如建立一个学生表 mysql> use goods; mysql> create table student(-> name varchar(4),-> age int,-> …

初学JavaWeb开发总结

0 什么是Web开发 Web: 全球广域网&#xff0c;又称万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站。 Web开发&#xff0c;就是开发网站的&#xff0c;如&#xff1a;淘宝、京东等等。 1 网站的工作流程 流程&#xff1a; 浏览器先向前端服务器请求前端资…

【计算机网络——应用层】http协议

文章目录 1. http协议1.1 http协议简介1.2 url组成1.3 urlencode与urldecode 2. http协议的格式2.1 http协议的格式2.2 一些细节问题 3. http的方法、状态码和常见响应报头3.1 http请求方法3.2 http状态码3.3 http常见的响应报头属性 4. 一个非常简单的http协议服务端5. http长…