拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Matlab热图绘制全攻略:从基础到专用热图实战

简介一套面向Matlab初、中级学习者的专用热图绘制资源包聚焦热图的多种定制化展现需求适合计算机、电子信息工程、数学等专业在课程设计、毕业设计或科研绘图中参考借鉴。包内共有105个文件以17个.m源代码文件为核心覆盖基本使用、颜色映射、分组、树状图、多层结构等不同场景的Demo另包含85张效果示例图、1份说明文档以及mlx实时脚本便于逐段对照理解每一类热图的生成逻辑。目前已有1102人学习下载适用于需要快速参考热图绘制思路、但需具备一定Matlab基础并能自行调试代码的读者。代码整体结构清晰可重点参考SHeatmap、SClusterBlock、SDendrogram等模块结合文档灵活调整配色、层级或分组方案从而高效完成从数据矩阵到专用热图的呈现提升可视化效率。1. 拿到「基于Matlab绘制各种专用热图」这套资源包先别急着解压看图片搜索这个标题的人大多数不是在找heatmap函数怎么用而是手里已经有一批数据想要能直接出图交差的脚本。生物信息学的差异基因表达谱、金融领域的相关性矩阵、工业现场的温度场分布第一眼呈现方式基本都靠热图。既然标题附带「源码图片说明文档」三个交付物这就不是一个简单的绘制脚本而是一整套从数据到图表的工程化输出方案。我会按「数据特征判定图类型 → 用 MatLab 原生函数搭建绘制框架 → 按场景定制专用形态 → 批量导出与验证」这条路径来梳理。无论你拿到的是哪种语言版本的热图资源最后落地的思路是一致的热图的成败不在颜色好不好看而在数据映射关系和坐标语义是否准确。2. 热图的三层底层逻辑数据归一化、颜色映射与坐标系2.1 先定坐标系离散分类轴还是连续数值轴Matlab 的热图工具看起来多其实只有两类坐标系。一类是heatmap函数生成的HeatmapChart对象X 轴和 Y 轴是离散的分类标签比如基因名、时间点、实验组别单元格颜色对应数值大小。另一类是基于imagesc、pcolor或surf的连续坐标系热图适合本身就带物理间距的数据比如空间坐标、光谱波长、时间序列。这两种坐标系的选择决定了后续所有定制方向。HeatmapChart的优势是自带行列标签、可交互排序、能叠加分组颜色条但它有一个麻烦坐标轴不是传统axes很多针对axes的旧版函数无法直接套用。反过来imagesc走的是标准axes可以用text、line、patch自由叠加元素但标签需要手动设置。% 离散分类热图词频矩阵 words {TCP;UDP;HTTP;MQTT}; timePoints {T1;T2;T3;T4}; data rand(4,4)*10; h heatmap(timePoints, words, data); h.Title 协议交互频次热图; h.XLabel 时间点; h.YLabel 协议类型;这段代码定义了一个 4x4 的随机数据矩阵行是协议类型列是采样时间点。heatmap接收三个参数时前两个是行列标签的 cell 数组第三个是数值矩阵。关键是理解heatmap不做数据归一化它只负责把数值线性映射到当前colormap的色阶上矩阵里的原始值可以通过单元格悬停查看。2.2 颜色映射让「红色代表危险」这件事不出错很多人画热图只调了一个colormap就收工但专用热图的核心在于「颜色语义清晰」。Matlab 的colormap只是把当前 figure 的颜色查找表换掉真正控制颜色与数值关系的参数是CLim对HeatmapChart来说是CLimits。默认情况下CLim会根据数据的最小最大值自动计算这就是很多热图颜色发灰、对比度差的原因。对于差异分析类的数据比如基因表达上下调我一般会用diverging色系且强制让 0 值对应中间色阶。常见做法是设定CLim对称比如数据范围是 -5 到 8就把CLim设为[-8 8]这样比 0 小的值和比 0 大的值在视觉上才不会互相掩盖幅值。% 连续数值热图的色阶截断 imagesc(data); colormap(flipud(redbluecmap)); % 白色在中间红蓝两端 caxis([-8 8]); % 老版本写法R2022a 之后用 clim colorbar;提示R2022a 开始caxis被标记为将要移除新代码统一使用clim(gca, [-8 8])HeatmapChart对应的是h.CLimits [-8 8]。热图颜色映射还有一个容易被忽略的坑imagesc会把矩阵的第一个元素放在左上方而heatmap第一个元素在左下方。如果你同时用两种方式画同一份数据看起来像是上下翻转了实际是 Y 轴方向的定义不同。统一校正 YDir 是一个必备习惯。2.3 数据归一化行归一、列归一还是全局归一「各种专用热图」的「专用」二字很大程度体现在归一化策略上。全局归一化适合所有数据同一量纲的场景行归一化z-score适合不同样本间比较趋势列归一化适合比较不同变量在同一样本上的表现。在资源包里最常见到的说明文档内容其实是描述了这几种归一化分别适用于什么场景。% 三种归一化方式对比 data randn(50, 20); % 行 z-score 归一化按行计算均值和标准差 rowNorm (data - mean(data,2)) ./ std(data,0,2); % 列 min-max 归一化到 [0,1] colMin min(data,[],1); colMax max(data,[],1); colNorm (data - colMin) ./ (colMax - colMin); % 全局百分比归一化 gNorm (data - min(data(:))) ./ (max(data(:)) - min(data(:)));选择归一化方式有一个判断标准热图上每一行代表独立样本比如多个基因在不同细胞系中的表达量优先行归一化每一列代表独立量纲的指标比如身高、体重、血压优先列归一化。如果所有数据是同一物理量的不同位置采样比如温度场那就不要归一化保留绝对数值反而更有工程意义。3. 把热图做成专用图概率密度、富集气泡与环形聚类形态3.1 概率密度热图用 histcounts2 替代散点图当数据量达到数万条记录时散点图会出现严重的重叠遮蔽问题此时应该画密度热图。原理是把二维平面划分为网格统计每个格子内的样本点数量再用颜色映射表示密度高低。这类图形在搜索引擎日志分析、传感器数据相关性检查中非常常见。% 用 histcounts2 构建密度网格 n 100000; x randn(n,1) * 2 1; y x .* 0.7 randn(n,1) * 0.5; [N, Xedges, Yedges] histcounts2(x, y, 50, 50); imagesc(Xedges(1:end-1), Yedges(1:end-1), log1p(N)); axis xy; % 修正 Y 轴方向让坐标原点在左下角 colormap(parula); c colorbar; c.Label.String log(样本数1);这里的N是 50x50 的计数矩阵log1p把计数做对数压缩避免出现个别高密度格子把整体色阶拉平。选用imagesc而不是heatmap是因为密度热图的横纵坐标是连续数值离散标签反而丢失空间信息。注意N需要转置因为histcounts2返回的矩阵第一维对应 X 的区间而imagesc的第一个参数对应 X 坐标。3.2 相关性热图与显著性星号的叠加方法相关性矩阵热图是「专用热图」里需求最稳定的一类。核心难点不是画颜色块而是把显著性检验的 p 值转成星号并精确标注到对应单元格上。HeatmapChart对象支持CellLabelFormat和FontColor但想要星号和数值同时出现在一个格子里需要一点变通。% 相关性热图 显著性星号 data randn(100, 6); [R, P] corrcoef(data); % 生成星号矩阵 stars strings(size(P)); stars(P 0.001) ***; stars(P 0.001 P 0.01) **; stars(P 0.01 P 0.05) *; labels strings(size(R)); labels(:) compose(%.2f, R); for i 1:size(R,1) for j 1:size(R,2) if i ~ j labels(i,j) labels(i,j) stars(i,j); end end end h heatmap(compose(V%d,1:6), compose(V%d,1:6), R); h.CellLabelFormat %s; h.CellLabelColor k;corrcoef一次返回两个矩阵相关系数R和 p 值P。用逻辑索引生成星号矩阵再和数值拼成一个字符串矩阵最后用CellLabelFormat %s让HeatmapChart显示字符串内容。有一点必须注意heatmap会把CellLabel自动替换为矩阵数值当你传入字符串矩阵时数值字段会失效所以ColorData仍然要用原始相关系数矩阵。3.3 聚类热图clustergram 的分组与树状图修剪带树状图的聚类热图常见于差异表达基因分析、宏基因组分箱结果展示在 Matlab 里不必手工做层级聚类再画树clustergram函数已经封装了完整流程。但它的默认输出是针对生物信息学的想要变成通用热图需要调整聚类距离和显示参数。% 用 clustergram 画聚类热图 geneData randn(300, 12); cg clustergram(geneData, ... Standardize, row, ... Cluster, all, ... RowLabels, compose(g%d, 1:300), ... ColumnLabels, compose(s%d, 1:12), ... Dendrogram, 15, ... Colormap, redbluecmap, ... DisplayRange, 3); % 为列添加分组颜色条 set(cg, ColumnGroupMarker, [1 1 1 2 2 2 3 3 3 4 4 4]);Standardize默认是none对差异表达热图来说通常要设为row也就是对每一行做 z-score 标准化。Dendrogram参数控制展示的树状图分支数15 表示最多显示 15 条分支分支太多时视觉上就是一团乱麻。DisplayRange控制颜色的上下限设置为 3 意味着 z-score 值超过 ±3 的颜色不再加深这避免个别极端值拉跨整体色阶。环形热图或称圆形热图是聚类热图的一种变体适用于变量数量多、名称长、线性排列放不下的场景。实现方案是把数据转换到极坐标系中沿圆周方向排列变量沿径向方向表示数值大小。基础思路是用polarscatter把每个数据点画成极坐标中的色块再叠加颜色映射但更稳妥的方式是用heatmap输出后把坐标轴隐藏叠一层极坐标网格。提示如果不需要树状图只是想把热图的行列顺序梳理出可复现的分组顺序clustergram提供了cg.RowLabels和cg.ColumnLabels读取重排后的顺序你可以把这些顺序导出后在heatmap里复用这样既能保留原矩阵数据又能保持聚类的视觉分组。3.4 三维热图把 XYZ 散点变成等值面标题热搜里出现了「三个维度的热图」和「决策曲线」这类需求通常指的不是 3D 曲面而是「X、Y 两个自变量 Z 一个因变量」构成的响应面图。数理统计里叫响应曲面工程领域叫热力图投影本质是把散点数据插值到均匀网格上再显示。% 散点插值成三维热图 x randn(2000,1); y randn(2000,1); z exp(-(x.^2 y.^2)) randn(2000,1)*0.05; [Xq, Yq] meshgrid(-3:0.1:3, -3:0.1:3); Zq griddata(x, y, z, Xq, Yq, natural); % 2D 投影热图等值面 contourf(Xq, Yq, Zq, 20); colorbar; colormap(jet); axis equal;griddata接受散点坐标和散点值插值到meshgrid生成的均匀网格上。natural是自然邻域插值对不均匀分布的散点效果最好但计算量大如果数据点超过 50000 个优先改用linear。插值之后的contourf填充等值线图比surf的俯视图更适合打印。三维热图还有一个分支是带时序的翻转热图即把数据矩阵画成surface格式通过修改view的角度来同时展示两个维度的变化趋势。这类图不适合做定量分析但信息密度大适合做汇报。4. 大数据量与多子图热图的性能陷阱与批量导出参数4.1 上万行矩阵的渲染加速方案heatmap和imagesc在面对大矩阵时的性能完全不在一个量级。heatmap的每个单元格都是一个图形对象行数超过 500 时渲染极慢内存占用还会指数增长。而imagesc本质是画一张纹理贴图渲染速度与矩阵大小几乎无关瓶颈只在颜色查找表的计算上。% 大矩阵热图统一用 imagesc 做底图 bigData randn(2000, 100); imagesc(bigData); colormap(plasma); ax gca; set(ax, XTick, 1:10:100, XTickLabel, compose(T%d, 1:10:100)); set(ax, YTick, 1:100:2000, YTickLabel, compose(Gene%d, 1:100:2000));这里把 2000x100 的矩阵用imagesc一次性绘制X 轴只标记每 10 个采样点Y 轴每 100 行打一个标签避免标签重叠。plasma是感知均匀的颜色映射全彩色视觉上比jet更平滑且不包含黑色区域。4.2 多热图并排tiledlayout 与 colorbar 对齐方案当需要把趋势图、聚类热图、富集条目热图拼成一张大图时常见的组合是「聚类热图趋势图富集条目」三联图tiledlayout比subplot更适合。它的TileSpacing和Padding属性可以精确控制子图间距而且colorbar可以通过Layout参数指定挂载到哪个 tile 上。% 三联图布局热图 趋势折线 富集条目热图 t tiledlayout(1, 3, TileSpacing, compact); % 左聚类热图 nexttile; imagesc(randn(30, 8)); colormap(ax1, redbluecmap); title(聚类热图); % 中趋势折线 nexttile; plot(randn(8, 8)); title(趋势图); % 右富集条目热图 nexttile; imagesc(randn(20, 15)); title(富集条目热图); cb colorbar; cb.Layout.Tile east; % 让 colorbar 只挂在最右侧colorbar默认会压缩相邻子图的宽度Layout.Tile east可以解决这个问题它把 colorbar 作为独立 tile 放到最右侧其他子图宽度自动适配不再互相挤压。这个组合形态在差异基因分析和组学数据展示里几乎成为模板。4.3 高清导出exportgraphics 的参数组合热图的最终去向是论文、报告或 PPT导出清晰度直接决定观感。老式的print -dpng输出默认会带白边分辨率还需要手动匹配PaperPosition。从 R2020a 开始exportgraphics成为推荐方案支持按像素分辨率导出且自动裁剪白边。% 高清导出参数模板 fig figure(Color, w, Position, [100 100 1200 800]); % ... 在这里画热图及其标注 ... exportgraphics(fig, heatmap_output.png, Resolution, 300);Resolution设置为 300 可以满足印刷需求PPT 投屏 150 足够BackgroundColor, none可以导出透明背景适用于深色 PPT 主题。如果导出PDF格式矢量图形会被保留文字清晰度最高但文件体积会膨胀。对于大数据量的热图导出 PDF 往往比 PNG 大一个数量级此时 PNG 优先。导出前的字体检查同样重要HeatmapChart的字体和字号独立于 figure 设置需要在h.FontSize中单独指定。多子图场景中最快的方法是统一字体参数set(findall(fig, -property, FontSize), FontSize, 10);5. 一个高兼容性的热图模板截断、标注与可复用封装资源包存在最核心的价值其实是提供「能直接复用」的代码骨架而非某一类具体热图的绘制脚本。我会按「数据进、图片出」的思路做一个最小模板把前面涉及的元素集中到一个函数里参数通过Name-Value传入适用于 80% 的专用热图需求。function h plotHeatmapTemplate(data, labelsX, labelsY, opts) arguments data (:,:) double labelsX (1,:) cell labelsY (1,:) cell opts.Title string 热图 opts.ColorMap string parula opts.CLim (1,2) double [] opts.ShowValue logical false opts.FontSize double 10 end h heatmap(labelsX, labelsY, data); h.Title opts.Title; h.Colormap opts.ColorMap; h.FontSize opts.FontSize; if ~isempty(opts.CLim) h.CLimits opts.CLim; end if opts.ShowValue h.CellLabelFormat %.2f; else h.CellLabelFormat none; end endarguments块是 R2019b 之后的语法配合heatmap的行列标签参数定义可以让不同数据源直接调用。这个模板解决的关键问题是每次画热图时不再复制粘贴一整段代码而是把可变参数标题、色阶范围、是否显示数值显式声明出来。「如何验证热图画得对」是比「画出热图」更高级一层的能力。我的做法是三步验证法第一步验证数据映射。在heatmap创建后调用h.ColorData应该与输入矩阵完全一致或等比例缩放。如果颜色与预期数值明显不符先检查是否因为missing值导致的数据压缩。第二步验证坐标对应关系。悬停热图单元格弹出的 DataTip 里显示的行列标签必须和数据表索引一一对应。第三步验证颜色截断位置。在colorbar上取中间位置颜色与colormap的中间行颜色比较确认尾端截断是否生效。颜色截断检查可以用一段很短的脚本自动化完成% 验证颜色截断是否正确对应 CLim cmap colormap; n size(cmap, 1); midColor cmap(round(n/2), :); % 取当前 colorbar 中间值对应的数据应为 CLim 的均值 expectedValue mean(clim(gca)); disp([热图中心色对应的数值: , num2str(expectedValue)]);如果你拿到手的某个热图资源图片与源码画出来的效果不一致优先排查数据文件是否被排序或过滤过其次是检查CLim是否为auto最后看 colormap 是否被后一段代码意外覆盖。大多数「热图颜色不对」的问题根源都不在绘图函数本身而是脚本执行顺序里某个生成 colorbar 或设置 colormap 的副作用。把模板函数和验证脚本固定下来「基于Matlab绘制各种专用热图」这件事才算真正闭环而不是每次换一组数据就从头折腾一遍配色和坐标。本文还有配套的精品资源点击获取
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门