当前位置: 首页 > article >正文

MATLAB | 绘图复刻(十八) | K-means 聚类分组热图

嘿,又双叒叕又双叒叕好久不见了,这期来个后台问的分组的热图,实际上就是绘制热图然后根据分组画一些线,但是matlab自带的热图heatmap不支持hold on操作,因此我们直接用pcolor来画,原图和复刻效果如下:

直接看步骤:

步骤解读

0 数据准备

这边我随机生成了一些数据,大家可以换成自己的,CName是分类后每个类的名字,大家可以增加一些识别每个类是什么种类的步骤,来将其换成自己的类名:

% 随便生成一些随机数据
rng(5)
Data = rand(50,10).*((1:10) + rand(1,10)) + randi([1,8],[50,1]);
Data = Data(:); Data = Data([end,1:end-1]); Data = reshape(Data, 50, []);

% 可以直接将上面部分删掉,然后
% Data = []% 自己的数据

K = 8; % kmeans 分组数
CName = compose('Class-%d', 1:K);

% 将相同组数据放在一起,并计算相关矩阵
[Class, Ind] = sort(kmeans(Data, K));
HMat = corr(Data(Ind,:).');

1 创建图窗并修饰

主要是设置坐标区域比例,增添X/Y轴刻度标签,增加标题,改改字体等:

%  坐标区域修饰
figure('Units','normalized', 'Position',[.1,.1,.6,.8])
ax = gca;
ax.NextPlot = 'add';
ax.Box = 'on';
ax.PlotBoxAspectRatio = [1,1,1];
ax.FontName = 'Times New Roman';
ax.FontSize = 14;
ax.YDir = 'reverse';
TickPos = find(diff([0;Class;K+1]) == 1);
ax.XTick = (TickPos(1:end-1) + TickPos(2:end) - 1)./2 - .5;
ax.YTick = ax.XTick;
ax.XTickLabel = CName;
ax.YTickLabel = CName;
ax.XTickLabelRotation = 30;
% 修改标题
ax.Title.String = 'XXXXXX K-means Centroid';
ax.Title.FontSize = 24;
ax.Title.VerticalAlignment = 'bottom';

2 绘制热图

由于pcolor每个格子的颜色是由上下左右四个格点的数值决定(比如左上角数值),因此直接用矩阵话最后一行最后一列的数值就不会被使用,导致画出来的热图少了一行一列,因此使用pcolor函数前需要先给矩阵增加一行一列NaN。

这部分代码最后一行的如果把注释符号去掉的话,能够隐藏边缘线。

% 绘制热图
N = size(Data, 1);
X = 0:N;
HMat(end+1, :) = nan;
HMat(:, end+1) = nan;
PHdl = pcolor(X, X, HMat);
PHdl.EdgeColor = [.3,.3,.3]; 
% PHdl.EdgeColor = 'none'; 

3 添加分组线

% 绘制分组线
for i = 2:K
    plot(ax, TickPos([i,i]) - 1, [0,N], 'Color','k', 'LineWidth',2)
    plot(ax, [0,N], TickPos([i,i]) - 1, 'Color','k', 'LineWidth',2)
end

4 绘制colorbar并调整颜色图

colorbar()
colormap(flipud(turbo))
clim([-1,1])


% colormap(slanCM(134))

大家可以尝试一下以下工具来获得更多种类的colormap:

  • https://www.mathworks.com/matlabcentral/fileexchange/120088-200-colormap

比如其中136号配色:

134号配色:

114号配色:


完整代码

% Grouped heatmap

% 随便生成一些随机数据
rng(5)
Data = rand(50,10).*((1:10) + rand(1,10)) + randi([1,8],[50,1]);
Data = Data(:); Data = Data([end,1:end-1]); Data = reshape(Data, 50, []);

% 可以直接将上面部分删掉,然后
% Data = []% 自己的数据

K = 8; % kmeans 分组数
CName = compose('Class-%d', 1:K);

% 将相同组数据放在一起,并计算相关矩阵
[Class, Ind] = sort(kmeans(Data, K));
HMat = corr(Data(Ind,:).');

%% 绘图部分
%  坐标区域修饰
figure('Units','normalized', 'Position',[.1,.1,.6,.8])
ax = gca;
ax.NextPlot = 'add';
ax.Box = 'on';
ax.PlotBoxAspectRatio = [1,1,1];
ax.FontName = 'Times New Roman';
ax.FontSize = 14;
ax.YDir = 'reverse';
TickPos = find(diff([0;Class;K+1]) == 1);
ax.XTick = (TickPos(1:end-1) + TickPos(2:end) - 1)./2 - .5;
ax.YTick = ax.XTick;
ax.XTickLabel = CName;
ax.YTickLabel = CName;
ax.XTickLabelRotation = 30;
% 修改标题
ax.Title.String = 'XXXXXX K-means Centroid';
ax.Title.FontSize = 24;
ax.Title.VerticalAlignment = 'bottom';

% 绘制热图
N = size(Data, 1);
X = 0:N;
HMat(end+1, :) = nan;
HMat(:, end+1) = nan;
PHdl = pcolor(X, X, HMat);
PHdl.EdgeColor = [.3,.3,.3]; 
% PHdl.EdgeColor = 'none'; 

% 绘制分组线
for i = 2:K
    plot(ax, TickPos([i,i]) - 1, [0,N], 'Color','k', 'LineWidth',2)
    plot(ax, [0,N], TickPos([i,i]) - 1, 'Color','k', 'LineWidth',2)
end

% 绘制colorbar并调整颜色图
colorbar()
colormap(flipud(turbo))
clim([-1,1])


% colormap(slanCM(134))

以上已经是完整代码,如果懒得复制可以去以下gitee仓库获取:

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

http://www.kler.cn/news/359831.html

相关文章:

  • 【MySQL数据库】MySQL高级语句(SQL语句进阶版)
  • Hive优化:Hive的执行计划、分桶、MapJoin、数据倾斜
  • 大模型输出的outputs为什么要取[0](即outputs[0])
  • STM32G4系列MCU的启动项配置
  • CIM系统:智慧城市的数字基石
  • 鸿蒙--进度条通知
  • Springboot+vue图书商城购物系统【附源码】
  • 列表(list)、元组(tuple)、字典(dictionary)、array(数组)-numpy、DataFrame-pandas 、集合(set)
  • Python知识点:基于Python技术和工具,如何使用Chainlink进行链下数据访问
  • 01 Druid未授权错误及解决方案
  • 命令行工具cURL 的用法
  • Python知识点:基于Python工具,如何使用Web3.py进行以太坊智能合约开发
  • Docker compose 安装Jenkins
  • Spring Boot助力中小型医院网站开发
  • ACM与蓝桥杯竞赛指南 基本输入输出格式三
  • 《Python游戏编程入门》注-第2章3
  • shell脚本每日一练1
  • 【独家:AI编程助手Cursor如何revolutionize Java设计模式学习】
  • 离线电脑 Visual Studio Community 2017:您的许可证已过期
  • PCL 基于FPFH特征描述子获取点云对应关系