MATLAB | 绘图复刻(五) | 带树状图的环形热图

news2024/9/22 17:28:34

本期教大家如何绘制带树状图的环状热图,要复刻的图片长这样:

复刻效果:

需要安装Statistics and Machine Learning Toolbox即统计与机器学习工具箱!!!

需要安装Statistics and Machine Learning Toolbox即统计与机器学习工具箱!!!


完整步骤

0 随机数据生成及变量定义

这里随便生成了一点数据:

% 随机生成数据
rng(5)
X=randn(100,80)+[(linspace(-1,2.5,100)').*ones(1,15),(linspace(.5,-.7,100)').*ones(1,15),...
                  (linspace(.1,-.7,100)').*ones(1,15),(linspace(.9,-.2,100)').*ones(1,15),...
                  (linspace(-.1,.7,100)').*ones(1,10),(linspace(-.9,-.2,100)').*ones(1,10)];
Y=randn(100,8)+[(linspace(-1,2.5,100)').*ones(1,2),(linspace(.5,-.7,100)').*ones(1,3),(linspace(-1,-2.5,100)').*ones(1,3)];
Data=corr(X,Y);

% 定义配色和颜色范围
CMap=parula();
%CMap=slanCM(136);
CLim=[-1,1];

% 随便定义变量名
XName{80}=[];
for i=1:80
    XName{i}=['slan',num2str(i)];
end
YName{8}=[];
for i=1:8
    YName{i}=['var',num2str(i)];
end

并定义了颜色和变量名,可以自行替换数据、配色和变量名。

1 图窗、坐标区域、基础数据定义

% 角度范围
theta1=pi/4;
theta2=-3*pi/2;
% 半径范围
R1=1;
R2=2;

% 角度及半径预处理 ==========================================================
theta3=(theta2-theta1)./size(Data,1);
theta4=theta1+theta3/2;
theta5=theta2-theta3/2;
theta6=2.7*pi/8;
R3=(R2-R1)./size(Data,2);
R4=R1+R3/2;
R5=R2-R3/2;

% 开始绘图 =================================================================
fig=figure('Units','normalized','Position',[0,0,1,1]);
fig.Color=[1,1,1];
ax=axes(fig);hold on
% ax.Position=[0,0,1,1];
ax.XLim=[-2,2];
ax.YLim=[-2,2];
ax.DataAspectRatio=[1,1,1];
ax.XColor='none';
ax.YColor='none';

这样会生成一个全屏空白窗口。

2 中心环形树状图生成

需要安装Statistics and Machine Learning Toolbox即统计与机器学习工具箱!!!

使用dendrogram函数绘图后进行一个极坐标变换即可,同时为了图象连接处能对起来,需要进行弧形的插值:

% 中心极坐标树状图
fig1=figure();
tree1=linkage(Data,'average');
[treeHdl1,~,order1]=dendrogram(tree1,0,'Orientation','top');
LineSet1=fig1.Children.Children;
maxY1=0;
for i=1:length(LineSet1)
    maxY1=max(max(LineSet1(i).YData),maxY1);
end
tS=linspace(0,1,50);
for i=1:length(LineSet1)
    tX=LineSet1(i).XData;
    tY=LineSet1(i).YData;
    tR=(maxY1-tY)./maxY1;
    tT=theta4+(theta5-theta4).*(tX-1)./(size(Data,1)-1);
    tR=[tR(1),tR(2).*ones(1,50),tR(4)];
    tT=[tT(1),tT(2)+tS.*(tT(3)-tT(2)),tT(4)];
    plot(ax,tR.*cos(tT),tR.*sin(tT),'Color','k','LineWidth',.7)
end
close(fig1)

3 侧面树状图生成

还是几乎完全相同的操作,不过弧形插值变成了两次:

% 绘制侧面树状图
fig2=figure();
tree2=linkage(Data.','average');
[treeHdl2,~,order2]=dendrogram(tree2,0,'Orientation','top');
LineSet2=fig2.Children.Children;
maxY2=0;
for i=1:length(LineSet2)
    maxY2=max(max(LineSet2(i).YData),maxY2);
end
tS=linspace(0,1,20);
for i=1:length(LineSet2)
    tX=LineSet2(i).XData;
    tY=LineSet2(i).YData;
    tR=R4+(R5-R4).*(tX-1)./(size(Data,2)-1);
    tT=theta6+(theta1-theta6).*(maxY2-tY)./maxY2;
    tR=[tR(1).*ones(1,20),tR(4).*ones(1,20)];
    tT=[tT(1)+(tT(2)-tT(1)).*tS,tT(3)+(tT(4)-tT(3)).*tS];
    plot(ax,tR.*cos(tT),tR.*sin(tT),'Color','k','LineWidth',.7)
end
close(fig2)

4 绘制环形热力图

由于MATLAB本身并不自带极坐标填充函数,因此这里直接fill函数一个一个格子硬画:;

% 绘制环形热力图
x=linspace(CLim(1),CLim(2),size(CMap,1))';
y1=CMap(:,1);y2=CMap(:,2);y3=CMap(:,3);
colorFunc=@(X)[interp1(x,y1,X,'pchip'),interp1(x,y2,X,'pchip'),interp1(x,y3,X,'pchip')];
tS=linspace(0,1,50);

Data=Data(order1,:);
Data=Data(:,order2);
for i=1:size(Data,2)
    for j=1:size(Data,1)
        tX=[i-1,i]./size(Data,2);
        tY=[j-1,j]./size(Data,1);
        tX=tX+1;
        tY=theta1+(theta2-theta1).*tY;
        tR=[tX(1).*ones(1,50),tX(2).*ones(1,50)];
        tT=[tY(1)+(tY(2)-tY(1)).*tS,tY(2)+(tY(1)-tY(2)).*tS];
        fill(ax,tR.*cos(tT),tR.*sin(tT),colorFunc(Data(j,i)),'EdgeColor',[1,1,1],'LineWidth',.7)
    end
end

5 绘制文本

要是中文字体乱码,请换成支持中文的字体,例如换成'FontName','宋体':

% 添加文本1
for i=1:length(order1)
    tT=theta4+(theta5-theta4).*(i-1)./(size(Data,1)-1);
    if tT>-pi/2
        text(ax,(1/30+2).*cos(tT),(1/30+2).*sin(tT),XName{order1(i)},...
        'FontSize',13,'FontName','Cambria','Rotation',tT./pi.*180);
    else
        text(ax,(1/30+2).*cos(tT),(1/30+2).*sin(tT),XName{order1(i)},...
        'FontSize',13,'FontName','Cambria','Rotation',tT./pi.*180+180,'HorizontalAlignment','right');
    end
end

% 添加文本2
for i=1:length(order2)
    text(ax,1/30,R4+(R5-R4).*(i-1)./(size(Data,2)-1),YName{order2(i)},...
        'FontSize',13,'FontName','Cambria');
end

6 添加colorbar

% 添加colorbar
colormap(CMap)
clim(CLim)
cb=colorbar();
cb.Position(2)=2/5;
cb.Position(4)=1/5;
cb.Position(1)=8/10;
cb.Position(3)=1/80;
cb.FontName='Cambria';
cb.FontSize=12;

7 更换配色

大家可能觉得颜色不好看,大家可以尝试下载文末所提到的压缩包,或者下载以下文章中提到的配色包,使用其中的配色让图象变得更好看一点:
https://slandarer.blog.csdn.net/article/details/127719784

比如将第0部分,随机数据生成及变量定义中定义配色的代码改为:

% 定义配色和颜色范围
CMap=slanCM(136);
CLim=[-1,1];

136号配色

141号配色

131号配色

111号配色

108号配色

105号配色

56号配色

175号配色

-1 完整代码

% @author : slandarer
% gzh  : slandarer随笔

% 随机生成数据
rng(5)
X=randn(100,80)+[(linspace(-1,2.5,100)').*ones(1,15),(linspace(.5,-.7,100)').*ones(1,15),...
                  (linspace(.1,-.7,100)').*ones(1,15),(linspace(.9,-.2,100)').*ones(1,15),...
                  (linspace(-.1,.7,100)').*ones(1,10),(linspace(-.9,-.2,100)').*ones(1,10)];
Y=randn(100,8)+[(linspace(-1,2.5,100)').*ones(1,2),(linspace(.5,-.7,100)').*ones(1,3),(linspace(-1,-2.5,100)').*ones(1,3)];
Data=corr(X,Y);

% 定义配色和颜色范围
CMap=parula();
CMap=slanCM(136);
CLim=[-1,1];

% 随便定义变量名
XName{80}=[];
for i=1:80
    XName{i}=['slan',num2str(i)];
end
YName{8}=[];
for i=1:8
    YName{i}=['var',num2str(i)];
end

% 角度范围
theta1=pi/4;
theta2=-3*pi/2;
% 半径范围
R1=1;
R2=2;

% 角度及半径预处理 ==========================================================
theta3=(theta2-theta1)./size(Data,1);
theta4=theta1+theta3/2;
theta5=theta2-theta3/2;
theta6=2.7*pi/8;
R3=(R2-R1)./size(Data,2);
R4=R1+R3/2;
R5=R2-R3/2;

% 开始绘图 =================================================================
fig=figure('Units','normalized','Position',[0,0,1,1]);
fig.Color=[1,1,1];
ax=axes(fig);hold on
% ax.Position=[0,0,1,1];
ax.XLim=[-2,2];
ax.YLim=[-2,2];
ax.DataAspectRatio=[1,1,1];
ax.XColor='none';
ax.YColor='none';

% 中心极坐标树状图
fig1=figure();
tree1=linkage(Data,'average');
[treeHdl1,~,order1]=dendrogram(tree1,0,'Orientation','top');
LineSet1=fig1.Children.Children;
maxY1=0;
for i=1:length(LineSet1)
    maxY1=max(max(LineSet1(i).YData),maxY1);
end
tS=linspace(0,1,50);
for i=1:length(LineSet1)
    tX=LineSet1(i).XData;
    tY=LineSet1(i).YData;
    tR=(maxY1-tY)./maxY1;
    tT=theta4+(theta5-theta4).*(tX-1)./(size(Data,1)-1);
    tR=[tR(1),tR(2).*ones(1,50),tR(4)];
    tT=[tT(1),tT(2)+tS.*(tT(3)-tT(2)),tT(4)];
    plot(ax,tR.*cos(tT),tR.*sin(tT),'Color','k','LineWidth',.7)
end
close(fig1)

% 绘制侧面树状图
fig2=figure();
tree2=linkage(Data.','average');
[treeHdl2,~,order2]=dendrogram(tree2,0,'Orientation','top');
LineSet2=fig2.Children.Children;
maxY2=0;
for i=1:length(LineSet2)
    maxY2=max(max(LineSet2(i).YData),maxY2);
end
tS=linspace(0,1,20);
for i=1:length(LineSet2)
    tX=LineSet2(i).XData;
    tY=LineSet2(i).YData;
    tR=R4+(R5-R4).*(tX-1)./(size(Data,2)-1);
    tT=theta6+(theta1-theta6).*(maxY2-tY)./maxY2;
    tR=[tR(1).*ones(1,20),tR(4).*ones(1,20)];
    tT=[tT(1)+(tT(2)-tT(1)).*tS,tT(3)+(tT(4)-tT(3)).*tS];
    plot(ax,tR.*cos(tT),tR.*sin(tT),'Color','k','LineWidth',.7)
end
close(fig2)


% 绘制环形热力图
x=linspace(CLim(1),CLim(2),size(CMap,1))';
y1=CMap(:,1);y2=CMap(:,2);y3=CMap(:,3);
colorFunc=@(X)[interp1(x,y1,X,'pchip'),interp1(x,y2,X,'pchip'),interp1(x,y3,X,'pchip')];
tS=linspace(0,1,50);
Data=Data(order1,:);
Data=Data(:,order2);
for i=1:size(Data,2)
    for j=1:size(Data,1)
        tX=[i-1,i]./size(Data,2);
        tY=[j-1,j]./size(Data,1);
        tX=tX+1;
        tY=theta1+(theta2-theta1).*tY;
        tR=[tX(1).*ones(1,50),tX(2).*ones(1,50)];
        tT=[tY(1)+(tY(2)-tY(1)).*tS,tY(2)+(tY(1)-tY(2)).*tS];
        fill(ax,tR.*cos(tT),tR.*sin(tT),colorFunc(Data(j,i)),'EdgeColor',[1,1,1],'LineWidth',.7)
    end
end

% 添加文本1
for i=1:length(order1)
    tT=theta4+(theta5-theta4).*(i-1)./(size(Data,1)-1);
    if tT>-pi/2
        text(ax,(1/30+2).*cos(tT),(1/30+2).*sin(tT),XName{order1(i)},...
        'FontSize',13,'FontName','Cambria','Rotation',tT./pi.*180);
    else
        text(ax,(1/30+2).*cos(tT),(1/30+2).*sin(tT),XName{order1(i)},...
        'FontSize',13,'FontName','Cambria','Rotation',tT./pi.*180+180,'HorizontalAlignment','right');
    end
end

% 添加文本2
for i=1:length(order2)
    text(ax,1/30,R4+(R5-R4).*(i-1)./(size(Data,2)-1),YName{order2(i)},...
        'FontSize',13,'FontName','Cambria');
end

% 添加colorbar
colormap(CMap)
clim(CLim)
cb=colorbar();
cb.Position(2)=2/5;
cb.Position(4)=1/5;
cb.Position(1)=8/10;
cb.Position(3)=1/80;
cb.FontName='Cambria';
cb.FontSize=12;


完整代码:

链接:
https://pan.baidu.com/s/1VVNozsMGzVKF45-ArZE_Dg?pwd=slan
提取码:slan

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

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

相关文章

对DataFrame的数据进行指定运算的DataFrame.transform()方法

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 对DataFrame中所有数据实施指定运算 例如:df1.transform(np.abs) 选择题 关于以下python代码说法错误的一项是? import pandas as pd import numpy as np df pd.DataFrame({&…

上班摸鱼软件

上班摸鱼软件前言思路采集组合自动下单发QQ报告结语前言 疫情几年,在家时间多,上班时间少。没事多在网上闲逛,偶然在知乎上看到一篇文章,说是买球也能稳赚不赔。我研究了一下,还真是这么回事。 简单来说,就…

转换通达信分钟数据,包括5分钟和1分钟数据

目录 1 前言 2 操作演示 3 代码 4 软件下载 5 stockpy整体功能介绍 1 前言 真正的市场高手不但要熟练掌握日线,对分钟线也要进行深入研究。缠中说禅在他的博客中讲到,年、季、月、周、日、60分钟、30分钟、5分钟、1分钟研究道理是相同的。粒度越细&…

华为云之ModelArts+AppCube带你识别101种西式美食

目录 1.注册并实名认证华为云账号 2.AI Gallery 订阅模型及部署 3. 获取访问秘钥 4.使用示例安装包创建 AppCube 应用 5. 创建 ModelArts 连接器 6. 应用修改 6.1 修改脚本 6.2 修改标准页面 6.3 运行及测试 1.注册并实名认证华为云账号 未注册及实名认证的话&…

2023年1月1日生效:2023年火车高铁儿童票最新规则及高铁火车2023儿童票怎么购买?

原文来源:https://www.caochai.com/article-4108.html 2023年火车高铁儿童票最新规则: 自2023年1月1日起生效,儿童购买高铁火车票将执行最新规则:按购票儿童年龄执行票价阶梯。 1、【免费】儿童年龄小于6周岁,无需购…

十六、状态管理——Vuex(2)

本章概要 mapMutationsmapStategetter 16.4 mapMutations 继续完善购物车程序,为购物车添加删除商品功能。删除商品同样要修改 store 中保存的购物车商品数据,因此继续在 mutations 选项中定义一个 deleteItem mutation。编辑 store 目录下的 index.j…

介绍idea 几个常用的插件

介绍idea 几个常用的插件1. Lombok2. MyBatis Log Free3. Database4. jsonparser5. Restful Fast Request5.1 插件配置5.1.1 基础配置5.1.2 全局请求头配置5.1.3 String生成配置5.2 插件使用5.2.1 调式接口(测试看)5.2.2 快速配置token5.2.3 保存、搜索A…

集成分布式锁架包(MySQL、Redis、Zookeeper)

前言: 疫情当下,大环境不好,自己又去了一家令人非常失望的单位,一直在996加班忙于业务代码,技术方面几乎等于零成长。但是,作为一个Coder,必须要挤出时间去学习与总结,不然就会被无情…

Emmet 使用 lorem 快捷生成随机文本填充html页面

快速使用 在编程中,我们也可以使用Lorem ipsum来填充页面,测试显示效果。主要是通过编辑器中自带的 Emmet 插件,识别以 lorem 开头的短语,生成指定格式的内容。以下介绍均以 vscode 为测试载体。 注意:lorem 短语需要…

Java-String 类·下

Java-String 类下5. 字符, 字节与字符串5.1 字符与字符串5.2 字节与字符串5.3 小结6.字符串常见操作6.1 字符串比较6.2 字符串查找6.3 字符串替换6.4 字符串拆分6.5 字符串截取6.6 其他操作方法7. StringBuffer 和 StringBuilder补充大家好,我是晓星航。今天为大家带…

计算机网络体系结构

目录常见的计算机网络体系结构计算机网络体系结构分层的必要性计算机网络体系结构分层思想举例计算机网络体系结构中的专用术语常见的计算机网络体系结构 TCP/IP体系结构相当于将OSI体系结构的物理层和数据链路层合并为网络接口层。并去掉了会话层和表示层。 由于TCP/IP在网络…

Java爬虫 爬取某招聘网站招聘信息

Java爬虫 爬取某招聘网站招聘信息一、系统介绍二、功能展示1.需求爬取的网站内容2.实现流程2.1数据采集2.2页面解析2.3数据存储三、获取源码一、系统介绍 系统主要功能:本项目爬取的XX招聘网站 二、功能展示 1.需求爬取的网站内容 2.实现流程 爬虫可以分为三个模…

[Kettle] Kettle界面介绍

启动Kettle后,弹出Kettle的欢迎界面 有关界面的构成和说明如下所示 ①标题栏:显示界面标题名称 ②菜单栏:分别有【文件】|【编辑】|【视图】|【执行】|【工具】|【帮助】六个菜单栏 ③工具图标栏:显示图形化的常用和重要的菜单项…

SAP MM采购定价过程字段解析

下面我们针对每一个字段进行解释和用途分析 : 1、 步骤:代表了创建PO时,哪个条件类型放到前面,哪个放到后面,如果步骤号相同,那就以谁先选择出来谁就在前面。 2、 计数:没有任何实际意义&a…

DaVinci:神奇遮罩

调色页面:神奇遮罩Color:Magic Mask神奇遮罩 Magic Mask基于人工智能技术,在检视器中绘制一个笔画,就能识别出笔画所在的对象,并以此自动创建遮罩。先确定要对画面上的物体还是人体做遮罩。若是对人体做遮罩&#xff0…

【闲来无聊写个几个小特效——五角星,小光圈,探照灯】

五角星,见过吧,如果是你,你如何使用代码写一个五角星呢?思考一下,你会说,先这样在那样就好啦,可是真正上手的时候却修修改改磕磕绊绊来看一下今天的五角星如何用几行代码实现 1.绘制五角星 四行…

Pytorch进行自定义Dataset 和 Dataloader 原理

1、自定义加载数据 在pytorch中,数据集对象被抽象为Dataset类,实现自定义的数据集需要继承Dataset,并实现相应的方法。 在学习Pytorch的教程时,加载数据许多时候都是直接调用torchvision.datasets里面集成的数据集,直…

GO第 4 章:运算符

第 4 章 运算符 4.1 运算符的基本介绍 运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等 运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等 算术运算符 赋值运算符 比较运算符/关系运算符 逻辑运算符 位运算符 其它运算 4.2 …

Java开发环境安装

总步骤 第一步:安装JDK(Java Development Kit,Java软件开发工具包) 第二步:安装IDEA(是Java语言的集成开发环境) 一、安装JDK Windows下最简单的Java环境安装指南 - 大博哥VV6 - 博客园 (cnblo…

微信小程序框架

框架 小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。 整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言…