MATLAB | 绘图复刻(十五) | 环形聚类树状图

本期复刻效果:

感觉出的聚类分析树状图绘制工具也不少了,未来可能会统一整理为一个工具包?(任重道远,道阻且长):


代码讲解

0 数据设置

写了比较多的注释应该比较易懂:

clc; clear; close all% 样品起名slan1 slan2 slan3...slan75
sampleName = compose('slan%d', 1:75);% 随机生成数据
% rng(10)
Data = rand(75,3);% 分类数
N = 5;% 分类名 Class-A Class-B...
className = compose('Class-%c', 64 + (1:N));% 设置字体
sampleFont = {'FontSize', 12, 'FontName', 'Times New Roman'};
classFont = {'FontSize', 18, 'FontName', 'Times New Roman', 'FontWeight', 'bold'};% 设置半径(树状图半径为1)
% 样本文本 类弧形内侧 类弧形外侧 类文本
RSet = [1+1/30, 1.22, 1.27, 1.35]; 

分类数N不宜设置太大,不然会出现比较多一个样本就是一个类的情况:


1 配色

这里使用的是MATLAB自带lines配色:

% 配色
CList = lines(N);

当然也比较推荐使用我写的slanCL配色包:https://slandarer.blog.csdn.net/article/details/129828666

给几个比较好看的配色:

% CList = slanCL(251,1:N);
% CList = slanCL(495,1:N);
% CList = slanCL(1838,1:N);
% CList = slanCL(319,1:N);
% CList = slanCL(361,1:N);
% CList = slanCL(455,1:N);

251

495

1838


2 创建绘图图窗

fig1 = figure('Units', 'normalized', 'Position', [.1,.1,.5,.8], 'Color', 'w');
ax1 = gca;
ax1.NextPlot = 'add';
ax1.DataAspectRatio = [1,1,1];
ax1.XColor = 'none';
ax1.YColor = 'none';
axis tight
fig2 = figure();

3 数据处理、绘制树状图、提取图形、关闭图窗

Z = linkage(Data,'average');
T = cluster(Z,'maxclust',N);
cutoff = median([Z(end-(N-1),3), Z(end-(N-2),3)]);
[LineSet, ~, order] = dendrogram(Z, 0, 'Orientation', 'top');
XSet = reshape([LineSet(:).XData], 4, []).';
YSet = reshape([LineSet(:).YData], 4, []).';
close(fig2)


4 环形树状图

% 角度转换数据预处理
TT = T(order);
theta1 = 0;
theta2 = pi*2;
theta3 = (theta2-theta1)./size(Data,1);
theta4 = theta1 + theta3/2;
theta5 = theta2 - theta3/2;
maxY = max(max(YSet));
tS = linspace(0,1,50);% 绘制环形树状图
tT = theta4 + (theta5-theta4).*(XSet-1)./(size(Data,1)-1);
tR = maxY-YSet;
tR = [tR(:,1), tR(:,2).*ones(1,50), tR(:,4)].';
tT = [tT(:,1), tT(:,2)+tS.*(tT(:,3)-tT(:,2)), tT(:,4)].';
plot(ax1, tR.*cos(tT), tR.*sin(tT), 'Color', 'k', 'LineWidth', .7);


5 添加标签文本

% 绘制样本名称标签
for i = 1:length(order)tT = theta4 + (theta5-theta4).*(i-1)./(size(Data,1)-1);if tT<pi/2 || tT>3*pi/2text(ax1, maxY.*RSet(1).*cos(tT), maxY.*RSet(1).*sin(tT), sampleName{order(i)},...'FontSize', 12, 'Rotation', tT./pi.*180, sampleFont{:});elsetext(ax1, maxY.*RSet(1).*cos(tT), maxY.*RSet(1).*sin(tT), sampleName{order(i)},...'FontSize', 12, 'Rotation', tT./pi.*180+180, 'HorizontalAlignment', 'right', sampleFont{:});end
end


6 绘制聚类信息

% 绘制分类信息
XSet = [XSet(:,1:2); XSet(:,3:4)];
YSet = [YSet(:,1:2); YSet(:,3:4)];
BSet = (YSet(:,1)-cutoff).*(YSet(:,2)-cutoff)<0;
HSet = (YSet(BSet,1)+YSet(BSet,2))./2;
Cset = TT(round(XSet(BSet,1)));
classNum = unique(TT, 'stable');for i = 1:length(classNum)% 绘制内部分类扇形tX = [find(TT==classNum(i),1,'first')-.5, find(TT==classNum(i),1,'last')+.5];tR = [maxY-HSet(Cset==classNum(i)), maxY];tT = theta4 + (theta5-theta4).*(tX-1)./(size(Data,1)-1);tR = [tR(1), tR(2).*ones(1,50), tR(1), tR(1).*ones(1,50)];tT = [tT(1), tT(1)+tS.*(tT(2)-tT(1)), tT(2), tT(2)+tS.*(tT(1)-tT(2))];patch(ax1, tR.*cos(tT), tR.*sin(tT), CList(i,:), 'EdgeColor', 'none', 'FaceAlpha', .25);% 绘制外部分类扇形tX = [find(TT==classNum(i),1,'first')-.2, find(TT==classNum(i),1,'last')+.2];tR = maxY.*RSet(1,2:3);tT = theta4 + (theta5-theta4).*(tX-1)./(size(Data,1)-1);tR = [tR(1), tR(2).*ones(1,50), tR(1), tR(1).*ones(1,50)];tT = [tT(1), tT(1)+tS.*(tT(2)-tT(1)), tT(2), tT(2)+tS.*(tT(1)-tT(2))];patch(ax1, tR.*cos(tT), tR.*sin(tT), CList(i,:), 'EdgeColor', 'none', 'FaceAlpha', .9);% 绘制分类信息标签tT = mean(tT);if tT<pitext(ax1, maxY.*RSet(4).*cos(tT), maxY.*RSet(4).*sin(tT), className{i}, 'Color', CList(i,:),...'FontSize', 16, 'Rotation', tT./pi.*180-90, 'HorizontalAlignment', 'center', classFont{:});elsetext(ax1, maxY.*RSet(4).*cos(tT), maxY.*RSet(4).*sin(tT), className{i}, 'Color', CList(i,:),...'FontSize', 16, 'Rotation', tT./pi.*180+180-90, 'HorizontalAlignment', 'center', classFont{:});end
end


完整代码

% clusterTreeDemo
% Copyright (c) 2024, Zhaoxu Liu / slandarerclc; clear; close all% 样品起名slan1 slan2 slan3...slan75
sampleName = compose('slan%d', 1:75);% 随机生成数据
% rng(10)
Data = rand(75,3);% 分类数
N = 5;% 分类名 Class-A Class-B...
className = compose('Class-%c', 64 + (1:N));% 设置字体
sampleFont = {'FontSize', 12, 'FontName', 'Times New Roman'};
classFont = {'FontSize', 18, 'FontName', 'Times New Roman', 'FontWeight', 'bold'};% 设置半径(树状图半径为1)
% 样本文本 类弧形内侧 类弧形外侧 类文本
RSet = [1+1/30, 1.22, 1.27, 1.35]; % 配色
CList = lines(N);
% CList = slanCL(251,1:N);
% CList = slanCL(495,1:N);
% CList = slanCL(1838,1:N);
% CList = slanCL(319,1:N);
% CList = slanCL(361,1:N);
% CList = slanCL(455,1:N);% =========================================================================
% 绘图部分代码
% -------------------------------------------------------------------------
% 创建绘图图窗
fig1 = figure('Units', 'normalized', 'Position', [.1,.1,.5,.8], 'Color', 'w');
ax1 = gca;
ax1.NextPlot = 'add';
ax1.DataAspectRatio = [1,1,1];
ax1.XColor = 'none';
ax1.YColor = 'none';
axis tight
fig2 = figure();% 数据处理、绘制树状图、提取图形、关闭图窗
Z = linkage(Data,'average');
T = cluster(Z,'maxclust',N);
cutoff = median([Z(end-(N-1),3), Z(end-(N-2),3)]);
[LineSet, ~, order] = dendrogram(Z, 0, 'Orientation', 'top');
XSet = reshape([LineSet(:).XData], 4, []).';
YSet = reshape([LineSet(:).YData], 4, []).';
close(fig2)% 角度转换数据预处理
TT = T(order);
theta1 = 0;
theta2 = pi*2;
theta3 = (theta2-theta1)./size(Data,1);
theta4 = theta1 + theta3/2;
theta5 = theta2 - theta3/2;
maxY = max(max(YSet));
tS = linspace(0,1,50);% 绘制环形树状图
tT = theta4 + (theta5-theta4).*(XSet-1)./(size(Data,1)-1);
tR = maxY-YSet;
tR = [tR(:,1), tR(:,2).*ones(1,50), tR(:,4)].';
tT = [tT(:,1), tT(:,2)+tS.*(tT(:,3)-tT(:,2)), tT(:,4)].';
plot(ax1, tR.*cos(tT), tR.*sin(tT), 'Color', 'k', 'LineWidth', .7);% 绘制样本名称标签
for i = 1:length(order)tT = theta4 + (theta5-theta4).*(i-1)./(size(Data,1)-1);if tT<pi/2 || tT>3*pi/2text(ax1, maxY.*RSet(1).*cos(tT), maxY.*RSet(1).*sin(tT), sampleName{order(i)},...'FontSize', 12, 'Rotation', tT./pi.*180, sampleFont{:});elsetext(ax1, maxY.*RSet(1).*cos(tT), maxY.*RSet(1).*sin(tT), sampleName{order(i)},...'FontSize', 12, 'Rotation', tT./pi.*180+180, 'HorizontalAlignment', 'right', sampleFont{:});end
end% 绘制分类信息
XSet = [XSet(:,1:2); XSet(:,3:4)];
YSet = [YSet(:,1:2); YSet(:,3:4)];
BSet = (YSet(:,1)-cutoff).*(YSet(:,2)-cutoff)<0;
HSet = (YSet(BSet,1)+YSet(BSet,2))./2;
Cset = TT(round(XSet(BSet,1)));
classNum = unique(TT, 'stable');for i = 1:length(classNum)% 绘制内部分类扇形tX = [find(TT==classNum(i),1,'first')-.5, find(TT==classNum(i),1,'last')+.5];tR = [maxY-HSet(Cset==classNum(i)), maxY];tT = theta4 + (theta5-theta4).*(tX-1)./(size(Data,1)-1);tR = [tR(1), tR(2).*ones(1,50), tR(1), tR(1).*ones(1,50)];tT = [tT(1), tT(1)+tS.*(tT(2)-tT(1)), tT(2), tT(2)+tS.*(tT(1)-tT(2))];patch(ax1, tR.*cos(tT), tR.*sin(tT), CList(i,:), 'EdgeColor', 'none', 'FaceAlpha', .25);% 绘制外部分类扇形tX = [find(TT==classNum(i),1,'first')-.2, find(TT==classNum(i),1,'last')+.2];tR = maxY.*RSet(1,2:3);tT = theta4 + (theta5-theta4).*(tX-1)./(size(Data,1)-1);tR = [tR(1), tR(2).*ones(1,50), tR(1), tR(1).*ones(1,50)];tT = [tT(1), tT(1)+tS.*(tT(2)-tT(1)), tT(2), tT(2)+tS.*(tT(1)-tT(2))];patch(ax1, tR.*cos(tT), tR.*sin(tT), CList(i,:), 'EdgeColor', 'none', 'FaceAlpha', .9);% 绘制分类信息标签tT = mean(tT);if tT<pitext(ax1, maxY.*RSet(4).*cos(tT), maxY.*RSet(4).*sin(tT), className{i}, 'Color', CList(i,:),...'FontSize', 16, 'Rotation', tT./pi.*180-90, 'HorizontalAlignment', 'center', classFont{:});elsetext(ax1, maxY.*RSet(4).*cos(tT), maxY.*RSet(4).*sin(tT), className{i}, 'Color', CList(i,:),...'FontSize', 16, 'Rotation', tT./pi.*180+180-90, 'HorizontalAlignment', 'center', classFont{:});end
end

以上已经是本文全部内容,若懒得一一获取代码,可以去以下gitee仓库获取全部代码:

https://gitee.com/slandarer/PLTreprint/

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

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

相关文章

Linux------环境变量

目录 前言 一、环境变量 二、添加PATH环境变量 三、HOME环境变量 四、查看所有环境变量 1.指令获取 2.代码获取 2.1 getenv 2.2main函数的第三个参数 2.3 全局变量environ 五、环境变量存放地点 六、添加自命名环境变量 七、系统环境变量具有全局属性 八、环境变…

芋道---实现可退回至申请人节点(附完整代码)

现有如下需求&#xff0c;审批人在退回申请时&#xff0c;想退回至申请人节点&#xff0c;但目前芋道并不支持退回至申请人节点&#xff0c;现做如下修改&#xff0c;实现该需求&#xff1a; 步骤一&#xff1a;设计流程模型 首先&#xff0c;我们在设计流程模型时&#xff0c…

【感想】幻想利用新技术就能不劳而获者往往成为韭菜

【背景】 最近由于AI的兴起,对技术感兴趣的业务同事也越来越多,这原本是一件好事。但是在仔细了解了他们的想法后,再结合外部环境对AI热潮熙熙攘攘的炒作,我又开始觉得这些对技术的所谓感兴趣,并不像我原先认识的那么积极。 【现实的复杂度不因技术而变化】 凡是有从0开…

0205-2-数据链路层

第 3 章 数据链路层 使用点对点信道的数据链路层 数据链路和帧 数据链路层使用的信道主要有以下两种类型&#xff1a; 点对点信道。这种信道使用一对一的点对点通信方式。广播信道。这种信道使用一对多的广播通信方式&#xff0c;因此过程比较复杂。广播信道上连接的主机很多…

Linux——网络通信TCP通信常用的接口和tcp服务demo

文章目录 TCP通信所需要的套接字socket()bind()listen()acceptconnect() 封装TCP socket TCP通信所需要的套接字 socket() socket()函数主要作用是返回一个描述符&#xff0c;他的作用就是打开一个网络通讯端口&#xff0c;返回的这个描述符其实就可以理解为一个文件描述符&a…

c高级 函数+Makefile

一、作业 1.写一个函数&#xff0c;输出当前用户的uid和gid&#xff0c;并使用变量接收结果 #!/bin/bash function fun(){retid -uret1id -gecho $ret $ret1 } retfun echo $ret二、练习回顾 1.分文件编译&#xff08;实现冒泡排序&#xff09; 正确的&#xff1a;将数组的…

HTTP/1.1 如何优化?

问你一句:「你知道 HTTP/1.1 该如何优化吗?」 我们可以从下面这三种优化思路来优化 HTTP/1.1 协议: 尽量避免发送 HTTP 请求在需要发送 HTTP 请求时&#xff0c;考虑如何减少请求次数减少服务器的 HTTP 响应的数据大小 下面&#xff0c;就针对这三种思路具体看看有哪些优化…

二叉树的统一迭代法#思路

前序遍历&#xff1a; class Solution: def preorderTraversal(self, root: TreeNode) -> List[int]: result[] st[] if root: st.append(root) while st: nodest.pop() if node ! None: if node.right: st.append(node.right) if node.left: st.append(node.left) st.appen…

git的常用命令有哪些?

Git 是一个流行的分布式版本控制系统&#xff0c;用于跟踪文件的变化、协作开发和管理代码。以下是一些常用的 Git 命令&#xff1a; 创建和克隆仓库&#xff1a; git init&#xff1a;在当前目录初始化一个新的 Git 仓库。git clone <仓库URL>&#xff1a;克隆一个远程仓…

【Java EE初阶十六】网络原理(一)

在网络原理中主要学习TCP/IP四层模型中的重点网络协议 1. 应用层 1.1 应用程序与协议 应用层是和程序员接触最密切的&#xff1b; 应用程序&#xff1a;在应用层这里&#xff0c;很多时候都是程序员自定义应用层协议&#xff08;步骤&#xff1a;1、根据需求&#xff0c;明确…

log4net的使用步骤

log4net的使用步骤 Log4net是一个基于.NET平台的开源日志记录组件&#xff0c;它可以帮助开发人员在应用程序中添加日志记录功能&#xff0c;支持多种日志级别&#xff0c;如DEBUG、INFO、WARN、ERROR等&#xff0c;这使得开发人员可以根据需要灵活地控制日志的输出。下面是lo…

SPSSAU【文本分析】|我的词库

我的词库 文本分析时&#xff0c;可能涉及到一些新词&#xff0c;比如‘内卷’&#xff0c;这个词很可能在词典中并未出现过&#xff0c;词库也不认识它。但研究者自己认识它&#xff0c;此时可将该词纳入到新词词库中&#xff0c;让系统统计词频等信息时也对该词进行统计。当…

【监控】spring actuator源码速读

目录 1.前言 2.先搂一眼EndPoint 3.EndPoint如何被注入 4.EndPoint如何被暴露 4.1.如何通过http暴露 4.2.如何通过jmx暴露 5.EndPoint是怎么实现监控能力的 6.知道这些的意义是什么 1.前言 版本&#xff1a;spring-boot-starter-actuator 2.6.3 阅读源码一定要带着疑…

小迪安全26WEB 攻防-通用漏洞SQL 注入 SqlmapOracleMongodbDB2 等

#知识点&#xff1a; 1、数据库注入-Oracle&Mongodb 2、数据库注入-DB2&SQLite&Sybase 3、SQL 注入神器-SQLMAP 安装使用拓展 数据库注入&#xff1a; 数据库注入-联合猜解-Oracle&Mongodb 1.Oracle数据库一般会在java上执行 参考:https://www.cnblog…

C/C++与汇编交互总结

1.汇编当中可以调用C函数&#xff0c;只需要"IMPORT"一下即可&#xff0c;如&#xff1a; change_vari_c PROCPUSH {R0,R1,LR}IMPORT core_res_cIMPORT temp_func_retEXPORT change_vari_cBL temp_func_retLDR R1,core_res_cSTR R0,[R1]POP {R0,R1,PC}ENDP 如果该C…

Rust HashMap详解及单词统计示例

在Rust中&#xff0c;HashMap是一种非常有用的数据结构&#xff0c;用于存储键值对。本文将深入介绍HashMap的特性&#xff0c;以及通过一个单词统计的例子展示其用法。 HashMap简介 HashMap是Rust标准库提供的用于存储键值对的数据结构。它允许通过键快速查找对应的值&#…

图数据库 之 Neo4j - 应用场景1(6)

Neo4j是一种图数据库&#xff0c;它专注于处理关系数据密集型的问题。由于其图结构的特性&#xff0c;Neo4j能够高效地存储、查询和分析连接数据。 以下是一些常见的Neo4j应用场景&#xff1a; 社交网络分析&#xff1a;通过建模和分析人际关系&#xff0c;可以揭示社交网络中…

PTA | Wifi密码

下面是微博上流传的一张照片&#xff1a;“各位亲爱的同学们&#xff0c;鉴于大家有时需要使用 wifi&#xff0c;又怕耽误亲们的学习&#xff0c;现将 wifi 密码设置为下列数学题答案&#xff1a;A-1&#xff1b;B-2&#xff1b;C-3&#xff1b;D-4&#xff1b;请同学们自己作答…

【详解】图的概念和存储结构(邻接矩阵,邻接表)

目录 图的基本概念&#xff1a; 图的存储结构 邻接矩阵&#xff08;GraphByMatrix&#xff09;&#xff1a; 基本参数&#xff1a; 初始化&#xff1a; 获取顶点元素在其数组中的下标 &#xff1a; 添加边和权重&#xff1a; 获取顶点的度&#xff1a; 打印图&#xf…

Unity所有关于旋转的方法详解

前言&#xff1a;欧拉角和四元数的简单描述 我们在Inspector面板上看到的rotation其实是欧拉角&#xff0c; 我们将Inspector面板设置成Debug模式&#xff0c;此时看到的local Rotation才是四元数。 Unity中的欧拉旋转是按照Z-X-Y顺规执行的旋转&#xff0c;一组欧拉旋转过程中…