使用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.hqwc.cn/news/499817.html

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

相关文章

uniapp实现-审批流程效果

一、实现思路 需要要定义一个变量, 记录当前激活的步骤。通过数组的长度来循环数据&#xff0c;如果有就采用3元一次进行选择。 把循环里面的变量【name、status、time】, 全部替换为取出的那一项的值。然后继续下一次循环。 虚拟的数据都是请求来的, 组装为好渲染的格式。 二…

javaWebssh网上超市销售管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh网上超市销售管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCA…

LeetCode41题:缺失的第一个正数(python3)

这道题写的时候完全没有思路&#xff0c;看了很久的题解&#xff0c;才总结出来。 class Solution:def firstMissingPositive(self, nums: List[int]) -> int:nums_set set(nums)n len(nums)for i in range(1, n 1):if i not in nums_set:return ireturn n 1

使用Haproxy搭建Web群集

1、Haproxy概述。 Haproxy是目前比较流行的一种群集调度工具&#xff0c;同类群集调度工具有很多&#xff0c;如LVS和Nginx。相比较而言&#xff0c;LVS性能最好&#xff0c;但是搭建相对复杂&#xff1b;Nginx的upstream模块支持群集功能&#xff0c;但是对群集节点健康检查功…

手机备忘录导到电脑上有什么方法简单点

在这个信息爆炸的时代&#xff0c;我们每天都在处理海量的信息和待办事项。手机备忘录里记录着重要的灵感、会议安排、待购物品清单……但每次想在电脑上继续编辑或查看时&#xff0c;我都感到无比头疼。难道就没有一种简单的方法&#xff0c;能让手机备忘录和电脑轻松同步吗&a…

Python 编程语言以及相关的库和工具来进行金融市场数据分析、策略开发和交易执行的过程。

Python 量化是指利用 Python 编程语言以及相关的库和工具来进行金融市场数据分析、策略开发和交易执行的过程。 Python 由于其简洁、易学、强大的生态系统和丰富的金融库而成为量化交易的首选编程语言之一。 量化交易在金融领域得到广泛应用&#xff0c;它允许交易者通过系统…

day57 集合 List Set Map

List实现类 List接口特点&#xff1a;元素有序 可重复 Arraylist 可变数组 jdk 8 以前Arraylist容量初始值10 jdk8 之后初始值为0&#xff0c;添加数据时&#xff0c;容量为10&#xff1b; ArrayList与Vector的区别&#xff1f; LinkList&#xff1a;双向链表 优点&#xff1…

数据处理安全评估:25项核心控制点

01 数据流与风险 数据处理活动是数据安全风险评估的核心&#xff0c;它是区别网络安全关键之一。以数据为中心&#xff0c;关注数据的流动过程&#xff0c;数据流转至的任何环节&#xff0c;都可能产生风险&#xff0c;任何可能接触到数据的角色都存在风险隐患。 关注数据的静…

【基于ChatGPT大模型】GIS应用、数据清洗、统计分析、论文助手、项目基金助手、科研绘图、AI绘图

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

【JavaEE】_HttpServletResponse类

目录 1. 核心方法 2. 关于setStatus(400)与sendError 2.1 setStatus(400) 2.2 sendError 3. setHeader方法 4. 构造重定向响应 4.1 使用setHeader和setStatus实现重定向 4.2 使用sendRedirect实现重定向 本专栏已有文章介绍HttpServlet和HttpServletRequest类&#…

【Python】Win创建虚拟环境运行Python

我习惯使用VS Code工具来编辑代码&#xff0c; 教程环境 Win11 Windows系统上&#xff0c;可以使用Python的内置工具venv来创建虚拟环境。以下是在Win上创建Python虚拟环境的步骤&#xff1a; 安装Python虚拟环境工具&#xff1a;首先确保系统中已经安装了Python 3。可以在Micr…

奇安信发布《2024人工智能安全报告》,AI深度伪造欺诈激增30倍

2024年2月29日&#xff0c;奇安信集团对外发布《2024人工智能安全报告》&#xff08;以下简称《报告》&#xff09;。《报告》认为&#xff0c;人工智能技术的恶意使用将快速增长&#xff0c;在政治安全、网络安全、物理安全和军事安全等方面构成严重威胁。 《报告》揭示了基于…