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…

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;就针对这三种思路具体看看有哪些优化…

【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…

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

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

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

目录 图的基本概念&#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;一组欧拉旋转过程中…

[力扣 Hot100]Day29 删除链表的倒数第 N 个结点

题目描述 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 出处 思路 两个指针间隔n&#xff0c;一趟遍历解决。 代码 class Solution { public:ListNode* removeNthFromEnd(ListNode* head, int n) {ListNode* phead;ListNode* …

【数据库】Mysql索引

1、什么是索引&#xff1f;为什么要用索引&#xff1f; 1.1、索引的含义 数据库索引&#xff0c;是数据库管理系统中一个排序的数据结构&#xff0c;以协助快速查询&#xff0c;更新数据库中表的数据。索引的实现通常使用B树和变种的B树&#xff08;MySQL常用的索引就是B树&am…

跟着pink老师前端入门教程(JavaScript)-day03

四、常量 概念&#xff1a;使用 const 声明的变量称为“常量”。 使用场景&#xff1a;当某个变量永远不会改变的时候&#xff0c;就可以使用 const 来声明&#xff0c;而不是let。 命名规范&#xff1a;和变量一致 常量使用&#xff1a; 注意&#xff1a;常量不允许重新…

数据库索引面试的相关问题

查看索引的执行计划 索引失效的情况 1、索引列上做了计算&#xff0c;函数&#xff0c;类型转换等操作。索引失效是因为查询过程需要扫描整个索引并回表。代价高于直接全表扫描。 Like匹配使用了前缀匹配符“%abc” 字符串不加引号导致类型转换。 原因&#xff1a; 常见索…

阿里云香港轻量应用服务器网络线路cn2?

阿里云香港轻量应用服务器是什么线路&#xff1f;不是cn2。 阿里云香港轻量服务器是cn2吗&#xff1f;香港轻量服务器不是cn2。阿腾云atengyun.com正好有一台阿里云轻量应用服务器&#xff0c;通过mtr traceroute测试了一下&#xff0c;最后一跳是202.97开头的ip&#xff0c;1…

酒店内部服务App开发常用的代码分享!

随着移动互联网的迅猛发展&#xff0c;智能手机已经成为人们生活中不可或缺的一部分&#xff0c;酒店作为服务行业的重要代表&#xff0c;为了提升客户体验、提高服务效率&#xff0c;纷纷开始开发内部服务App。 这些App不仅可以帮助酒店实现内部管理的便捷化&#xff0c;还能…