使用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.mzph.cn/news/710471.shtml

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

相关文章

MySQL 使用 pt-archiver 删除数据

文章目录 前言1. 环境准备1.1 模拟造数1.2 工具安装 2. 删除数据2.1 批次删除表2.2 原理解析2.3 批处理思路 后记 前言 在线核心业务都会有日志表&#xff0c;随着业务持续运行&#xff0c;日志表每天都在增大&#xff0c;最后超过阈值触发空间使用率告警。DBA 处理空间告警时…

爬取某牙视频

爬取页面链接&#xff1a;游戏视频_游戏攻略_虎牙视频 爬取步骤&#xff1a;点进去一个视频播放&#xff0c;查看media看有没有视频&#xff0c;发现没有。在xhr中发现有许多ts文件&#xff0c;但这种不是很长的视频一般都有直接的播放链接&#xff0c;所以目标还是找直接的链…

数据结构-----再谈String,字符串常量池,String对象的创建、intern方法的作用

文章目录 1.字符串常量池1.1. 创建对象的思考2.2. 字符串常量池(StringTable)1.3. 再谈String对象创建1.4. intern方法 1.字符串常量池 1.1. 创建对象的思考 下面两种创建String对象的方式相同吗&#xff1f; public static void main(String[] args) {String s1 "hel…

【Elasticsearch查询】深度查询

文章目录 深度查询from/toScroll如何查询重要笔记保持搜索上下文环境存活手动清除切片 Search After排序查询注意Demo 深度查询 from/to 运行Search进行查询时&#xff0c;可以使用from和size参数对结果进行分页。 from参数定义了要获取的第一个结果的偏移量。size参数表示允…

我用 Navicat 的这些技能少加了好多班,也为公司挣了不少w

今天又用 Navicat 解决了一个数据同步的需求&#xff0c;财务又到账一笔收入....... 本文我将结合我过去的实践&#xff0c;给大家推荐一款数据库的运维工具。给大家呈现一下竟然可以用 Navicat 解决这些实际问题 。 熬了几个夜&#xff0c;毫无保留地将这些技能分享&#xf…

使用R语言进行判别分析

一、样本数据描述 2016年全国31个省、直辖市、自治区城镇居民人均消费支出水平划为2类&#xff0c;其中北京和上海划为一类&#xff0c;其余地区划为一类&#xff0c;将广东和西藏作为待判样本&#xff0c;具体划分数据如下表&#xff0c;试对数据进行判别分析&#xff0c;并将…

vue中动态引入图片

分析 很多时间&#xff0c;不管是vue2&#xff0c;还是vue3开发中都会遇到&#xff0c;动态渲染图片的功能&#xff0c;但是为什么我们直接将图片的路径直接赋值给变量的时候&#xff0c;图片渲染不出来&#xff0c;而通过require引入加载图片后却能正常渲染呢&#xff1f;主要…

解释什么是内连接、左连接和右连接,并给出每种连接的SQL示例

在关系型数据库中&#xff0c;连接&#xff08;JOIN&#xff09;是一种在查询中组合来自两个或多个表的行的方法。这些表通过一个或多个列中的相关值关联起来。SQL 提供了几种类型的连接&#xff0c;每种连接在处理表之间的关系和数据检索时都有其特定的方式。最常见的连接类型…

华为HarmnyOS TypeScript基础语法快速入门

华为HarmnyOS TypeScript基础语法快速入门 一、JavaScript、TypeScript、ArkTS二、TypeScript基础语法1. 基础类型2. 条件语句3. 函数4. 类5. 模块6. 迭代器 一、JavaScript、TypeScript、ArkTS ArkTS是HarmonyOS优选的主力应用开发语言。它在TypeScript&#xff08;简称TS&am…

Flask+Gunicorn中文乱码解决方案

在使用FlaskGunicorn部署应用时&#xff0c;发现中文的输出存在乱码的现象。这是因为Python的默认编码是ASCII&#xff0c;而ASCII并不支持中文字符。 解决Python中文乱码问题的首要任务是确保使用合适的编码方式。当你处理中文字符时&#xff0c;应该使用UTF-8编码。UTF-8是一…

Axios入门

1.概念 Axios是一个开源的可以用在浏览器和node.js的异步通信框架&#xff0c;他的主要功能是实现Ajax异步通信 2.Axios入门程序 2.1.准备json格式的文件 {"name": "小明","address": {"street": "雁塔","city"…

动画原理:表面形变算法的思考与总结

前言&#xff1a; 之前我的文章 Mesh形变算法_mesh算法-CSDN博客就有大致的讨论过&#xff0c;介绍的也比较粗略&#xff01;现在主要是想在Triangulated Surface Mesh Deformation方向上更深入的讨论一下&#xff01;结合今年我对这一块的学习谈谈我的理解~ 下面要介绍大致几…

Java设计模式——桥连模式

桥接模式简单来说就是通过将抽象部分和具体部分分离&#xff0c;使它们可以独立地变化。如果你的一个类存在多个变化维度&#xff08;如抽象和具体的实现&#xff09;。若使用继承来处理这些变化&#xff0c;将会导致类层次结构的急剧增加&#xff0c;难以管理和维护。并且&…

MySQL(基础篇)——函数、约束

一.函数 1.定义 函数是指一段可以直接被另一段程序调用的程序或代码。 2.字符串函数 常见如下&#xff1a; -- 字符串拼接 SELECT CONCAT(hello,MySql) AS CONCAT -- 将字符串全部转为小写 SELECT LOWER(HEllo MYSql) AS LOWER -- 将字符串全部转为大写 SELECT UPPER(Hello…

环境配置 |Jupyter lab/Jupyter Notebook 安装与设置

ipynb使用Jupyterlab/Jupyter Notebook 来编写Python程序时的文件,在使用时,可以现转换为标准的.py的python文件 1.Jupyter Lab 1.1.下载安装 环境&#xff1a;Linux pip install jupyterlab 1.2.使用 jupyter lab 点击后进入 1.3.jupyter lab更换内核 因为我的是在anac…

178文章复现:基于matlab的微震图像去噪

文章复现&#xff1a;基于matlab的微震图像去噪&#xff0c;利用同步压缩连续小波变换进行自动微震去噪和起始检测&#xff0c;SS-CWT 可对时间和频率变化的噪声进行自适应过滤&#xff0c;可以去除小幅值信号中的大部分噪声&#xff0c;检测地震事件并估算地震发生时间。程序已…

数据结构之树结构(上)

存储方式 数组存储方式的分析 优点&#xff1a;通过下标方式访问元素&#xff0c;速度快。对于有序数组&#xff0c;还可使用二分查找提高检索速度。 缺点&#xff1a;如果要检索具体某个值&#xff0c;或者插入值&#xff08;按一定顺序&#xff09;会整体移动&#xff0c;效…

C++实现计算复杂数学表达式

本文使用C实现Shunting-yard算法&#xff0c;将中缀表达式转换为后缀表达式&#xff0c;然后使用后缀表达式计算结果&#xff0c;实现了目前支持以下 四则运算&#xff08;、-、*、/&#xff09;开平方&#xff08;^&#xff09;取基数为 10 的对数&#xff08;L&#xff09;小…

小(2)型土石坝安全监测设施配置详解

小(2)型土石坝的安全监测是确保大坝稳定、安全运行的重要环节。为此&#xff0c;合理配置安全监测设施显得尤为重要。以下是对小(2)型土石坝安全监测设施配置的详细介绍。 一、渗流量监测 渗流量是反映大坝安全状况的关键指标之一。为准确监测渗流量&#xff0c;我们采用仪器量…

【大数据】Flink SQL 语法篇(十):EXPLAIN、USE、LOAD、SET、SQL Hints

《Flink SQL 语法篇》系列&#xff0c;共包含以下 10 篇文章&#xff1a; Flink SQL 语法篇&#xff08;一&#xff09;&#xff1a;CREATEFlink SQL 语法篇&#xff08;二&#xff09;&#xff1a;WITH、SELECT & WHERE、SELECT DISTINCTFlink SQL 语法篇&#xff08;三&…