尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MATLAB科研绘图:掌握图层与坐标尺,轻松复刻期刊级图表

MATLAB科研绘图:掌握图层与坐标尺,轻松复刻期刊级图表 简介MATLAB绘图复刻资源包面向需要提升科研论文配图质量的中高级MATLAB使用者覆盖分组柱状图、热图与差异气泡图、分层聚类分析、组合泰勒图、折线图误差棒柱状图散点抖动等18种常见复杂图表的完整复刻实现。压缩包约59.05MB以MATLAB脚本与数据文件为主便于直接运行修改。已有179人学习下载适合生物医学、地学、工程等领域的图表排错与样式参考。资源按复刻序号组织每个案例包含从数据整理到成图的完整代码并附有灰色背景、图片叠加、颜色修改、标签旋转等细节调整思路可帮助读者快速套用并生成符合期刊要求的组合图形。1. 复刻科研绘图的底层逻辑画布、层序和坐标尺复刻一批科研图难点从来不在“plot 还是 heatmap 怎么调用”而在于三层顺序先定画布尺寸和坐标映射再按图层叠加图形对象最后统一字体、色板和导出参数。标题里“分组柱状图、热图差异气泡图、分层聚类分析图、泰勒图、环形热图”看起来是七八种不同技法落到 MATLAB 里其实就是两件事把数据重排成矩阵把图形对象按正确的层级叠加。谁先画、谁后画谁透明、谁描边直接决定一张图能不能达到期刊排版要求。例如“热图差异气泡图”和“分层聚类分析图”共用同一张表达矩阵差别只在后者多算一次linkage“折线图误差棒柱状图散点抖动灰色背景”看起来是五种图叠在一张图里实际只有两个图层一个放柱体和误差棒一个放折线和抖动散点。最容易忽略的是坐标尺柱状图用分类坐标热图用格点坐标泰勒图和环形热图走极坐标坐标尺一变所有标注和间距都要重算。这和常见 matlab 绘图教程里“跟着敲一遍”有根本差别跟着敲只能拿到一张图理解了图层和坐标尺之后拿到的是能换数据、换颜色、换尺寸而不塌的模板。下面按对比图、热图、组合图、极坐标图四类逐个拆开。2. 分组柱状图、堆叠柱状图加哑铃图三步走通的对比数据作图2.1 分组柱状图的第一步是重排数据矩阵不是找绘图函数我见过大量在分组柱状图里卡住的人问题不在bar不会用而是手头数据是“长表”结构一行一个样本一列一个分组再加一列数值。bar虽然也能吃timetable和部分表格式输入但对分类顺序、误差棒叠加、图例顺序都不好控制。稳妥做法是先把数据重排成“行是类别、列是分组”的数值矩阵。下面用 R2023b 里很常见的参与者实验数据做示例。dataTable里有三列分别是分组名、指标名、测量值目标是画出三个指标在三个分组下的分组柱状图。% 从长表重排成分组柱状图需要的矩阵 % dataTable: 列分别为 group, metric, value [groups, ~, gid] unique(dataTable.group, stable); [metrics, ~, mid] unique(dataTable.metric, stable); nG numel(groups); nM numel(metrics); data nan(nM, nG); for i 1:nM for j 1:nG idx (mid i) (gid j); data(i, j) mean(dataTable.value(idx), omitnan); end end figure(Color, w, Position, [100 100 760 420]); b bar(data, grouped); b(1).FaceColor [0.20 0.35 0.65]; b(2).FaceColor [0.25 0.60 0.40]; b(3).FaceColor [0.85 0.45 0.10]; set(gca, XTickLabel, metrics, Box, off, TickDir, out); ylabel(mean value); legend(groups, Location, best);逻辑上分成四段unique拿分类列表和索引for循环按行列索引填均值bar(data, grouped)把矩阵的每一列自动变成一组柱子最后通过b(1)、b(2)分别设置每一组柱子的面颜色。这里的核心参数有三个grouped是 MATLAB 的默认布局显式写出是为了防止和stacked混淆XTickLabel必须和data的行数一一对应b(k)的顺序是“列的顺序”所以必须先确认groups里的排序再做图例。如果类别特别多比如 15 个指标柱子会挤在一起。此时优先改BarWidth比如set(b, BarWidth, 0.6)不要靠拉宽图形窗口来缓解窗口尺寸一变字距和刻度密度全乱。2.2 堆叠柱状图和哑铃图的叠加hold on 与图层顺序堆叠柱状图和哑铃图解决的问题不一样。堆叠图看重“总量中每个部分占多少”哑铃图看重“同一指标在两个时间点之间的位移”。很多论文会把这两种图并排放置让读者从不同角度理解同一批数据。堆叠柱状图可以直接吃上一步的data矩阵% 堆叠柱状图每个指标一列组间纵向堆叠 figure(Color, w, Position, [100 100 520 420]); b2 bar(data, stacked); b2(1).FaceColor [0.20 0.35 0.65]; b2(2).FaceColor [0.25 0.60 0.40]; b2(3).FaceColor [0.85 0.45 0.10]; % 堆叠柱总高度上的总误差棒 yTotal sum(data, 2); errTotal [0.3 0.5 0.4]; % 实际应从原始数据计算总标准差 hold on; errorbar(1:nM, yTotal, errTotal, k, LineStyle, none, LineWidth, 1.2);堆叠图的误差棒要特别注意如果误差棒代表“总量”的波动就画在堆叠柱顶部如果代表“某一个分组贡献”的波动就要画在该分组色块的内部中间位置而不是柱子顶部。画后者时需要先拿到该分组色块的顶边高度也就是cumsum(data, 2)再做偏移。哑铃图本质是“两条短横线加一个连接线”MATLAB 里用plot加两次scatter最省事% 哑铃图同一指标在 pre/post 两个时间点的变化 pre [8.2 9.1 10.4 7.6 8.8]; post pre [1.3 0.8 -0.4 2.1 1.0]; x 1:numel(pre); figure(Color, w, Position, [100 100 560 360]); hold on; for i x plot([i i], [pre(i) post(i)], -, Color, [0.45 0.45 0.45], LineWidth, 1.5); end scatter(x, pre, 55, [0.20 0.35 0.65], filled); scatter(x, post, 55, [0.85 0.35 0.25], filled); set(gca, XTick, x, XTickLabel, string(1:numel(pre)), ... Box, off, YGrid, on);这段代码的关键是plot画连接线两次scatter覆盖到两端点上。连接线先画端点点后画颜色才能盖住线头避免出现“线穿过点”的粗糙感。若要表现配对样本应该把同一指标的 pre 和 post 用同一条线连接这正是哑铃图相比分组柱状图的优势所在。YGrid只开横向网格不显示纵向网格视觉上更干净。2.3 分组柱状图与哑铃图共用的配色和标注规范两套图出现在同一篇论文里时最好保持“同一分组同一颜色”的对应关系否则审稿人会花时间来回找图例。下面的表格是科研绘图里常用的参数搭配我一般固定成模板参数分组柱状图堆叠柱状图哑铃图柱体颜色分组敏感建议不超过 4 组组分敏感建议不超过 5 层端点区分两端颜色对比要强描边EdgeColor设为白或灰同左避免深色描边分割过重连接线用中灰误差棒黑色实线LineWidth1.0 以上总量误差画顶边分量误差画内部通常不画误差棒字体坐标轴与图例统一 8pt 以上同左同左透明不建议不建议可以用MarkerFaceAlpha0.8配色上避开默认的 parula 和 jet 在柱状图里的使用。柱状图面积大饱和色块并排会互相抢占视觉权重我的常用做法是第一组用低饱和蓝第二组用低饱和绿第三组用橙第四组用灰。以上面的哑铃图为例端点用 [0.20 0.35 0.65] 与 [0.85 0.35 0.25]明度拉开打印成灰度稿时仍可区分。3. 热图、差异气泡图与分层聚类分析图同一张表达矩阵的三个切面3.1 先用 linkage、dendrogram 把分层聚类的顺序算出来“热图差异气泡图”和“分层聚类分析图”是生物信息学里最常见的组合尤其在差异基因环形热图、聚类热图趋势图这类场景中。常见的错误是一上来就heatmap等图出来再手动调行序。行序一动聚类树和热图就对不上了。正确顺序是先把层级聚类顺序算出来再把它作为索引传给热图。下面以一个 10 个样本、6 个特征的随机矩阵为例% 模拟数据10 个样本 x 6 个特征 X randn(10, 6); % 样本间距离用相关性距离避免量纲影响 D pdist(X, correlation); L linkage(D, average); % 优化叶子顺序减少树状图交叉 ord optimalleaforder(L, D); % 查看聚类顺序 disp(ord);pdist计算的是两两样本之间的距离默认欧氏距离但对表达谱数据我更推荐correlation距离因为它关注的是表达趋势是否一致而不是绝对数值大小。linkage的average是生物数据里最常用到的连接方式它用类间平均距离对离群值不像complete那么敏感也不像single那样容易链状拉长。optimalleaforder做一次叶子顺序重排能让树状图和热图里的交叉明显减少。这个函数存在时就调用计算量对几千个样本以下的问题几乎可以忽略。3.2 热图加差异气泡图叠加坐标对齐到格点是关键MATLAB 内置的heatmap函数出图快但它有自己的格点坐标系XDisplayData这类属性在 R2023b 里还受版本影响叠加气泡时经常出现半格偏移。我的做法是结构调整多、还要上气泡的图直接用imagesc做底再用scatter叠加气泡这样两个函数共享同一个坐标轴格点对齐没有歧义。% imagesc 热图 差异气泡图叠加 figure(Color, w, Position, [100 100 760 620]); imagesc(X(ord, :)); % 按聚类顺序重排行 colormap(flipud(jet)); % 观察需求研究型热图常用蓝白红 caxis([-2 2]); % 截断极值防止个别离群值拉平色阶 hold on; % 生成网格坐标格点中心就是气泡位置 [xg, yg] meshgrid(1:size(X,2), 1:size(X,1)); % 气泡大小由另一个统计量控制例如差异倍数或 -log10(p) bubbleSize 100 800 * rand(size(X)); scatter(xg(:), yg(:), bubbleSize(:), [0 0 0], filled, ... MarkerFaceAlpha, 0.35, MarkerEdgeColor, none); % 格点边框线模仿热图分格 set(gca, XTick, 1:size(X,2), YTick, 1:size(X,1), ... YTickLabel, sampleNames(ord), Box, on, ... XAxisLocation, top, TickDir, out); axis tight;imagesc的格点中心恰好落在1:n上所以meshgrid生成的坐标和矩阵元素位置一一对应气泡圆心永远对准格子中心这是叠加差异气泡图时最省心的方式。bubbleSize是线性映射实际做科研图时建议先把差异倍数做log2转换让气泡面积不再被个别极值主导。caxis在这里做了硬截断相当于把三倍标准差以外的值全部压到色标端点否则热图颜色会因一个离群样本整体变淡。热图 气泡图的结构里行顺序由 3.1 的ord控制列顺序如果不做聚类就按指标原本顺序排列。如果列数超过 20最好也给列做一次linkage否则热图横向没有信息结构读者只能逐列扫读。3.3 热图配色与差异气泡图的截断策略下面的表格对比了三种热图实现方式便于按实际场景选择需求imagescheatmapclustergram叠加气泡/散点最顺手需处理坐标偏移不推荐显示行名/列名手动设置自动自动内置聚类树无无有但不能直接在图上加散点自定义色标截断caxisColorLimits有适合数据规模千级以内万级以内中等三个方案里clustergram对“带树状图的分层聚类分析图”最省事但它把聚类和热图绑成整体想在里面插散点、加注记都会绕路。我的判断标准很简单只要最终成图里要有热图之外的第二类信息就放弃clustergram走pdistlinkageimagesc的组合代价是行名和色标要自己摆但自由度换来的是后面叠加任何图形对象都不必再跟内置对象抢图层。色标方面研究型论文里“蓝-白-红”比 jet 更稳重。flipud(jet)只是应急真正可复用时建议做成[0.20 0.40 0.80; 1 1 1; 0.80 0.20 0.20]的三色映射再用interp1插值到 256 行。4. 折线图 误差棒 柱状图 散点抖动再加灰色背景和图片叠加的组合图层4.1 误差棒口径标准差、标准误还是置信区间组合图里误差棒是最容易被审稿人追问的部分。errorbar本身只管画线不管数据口径图形上看着都差不多但图注里必须写明用的是 SD、SEM 还是 95% CI。三者的数值差别很大直接决定误差棒的长短和统计显著性外观。口径计算适用场景图上表现标准差 SDstd(x)描述数据离散度误差棒长反映个体差异标准误 SEMstd(x)/sqrt(n)推断样本均值误差棒短随 n 增大缩小95% 置信区间tinv(0.975, n-1)*SEM参数估计区间宽可直接看显著性线索做分组柱状图和折线图时我习惯在同一张图里只用一种口径并且把样本量n写进图注。errorbar的CapSize参数在 R2023b 里默认很小导出 600dpi 后几乎看不见刻度帽建议显式设置errorbar(..., CapSize, 6)。4.2 散点抖动rng 固定随机种子是第一步散点抖动的目标是把重叠的原始数据点摊开让人看到样本密度。抖动幅度需要和柱状图宽度匹配柱子宽度是 0.6抖动幅度就不应超过 0.3否则点会溢出柱子边界。实现时先固定rng保证每次生成图的结果一致这是科研绘图里最容易被忽略的细节。% 柱状图 原始散点抖动 rng(42); % 固定随机种子复刻时散点位置不变 x 1:5; yMean [12.3 14.1 9.8 11.2 15.4]; errBar [0.8 1.0 0.7 0.9 1.1]; n 8; % 每组的样本量 % 生成原始数据点均值附近加入组内方差 rawData yMean randn(numel(yMean), n) .* errBar; figure(Color, w, Position, [100 100 680 420]); hold on; bar(x, yMean, 0.55, FaceColor, [0.85 0.45 0.10], ... EdgeColor, w, LineWidth, 1); errorbar(x, yMean, errBar, k, LineStyle, none, ... LineWidth, 1.2, CapSize, 6); % 抖动散点x 方向抖动幅度为柱宽的一半y 方向用原始值 for i 1:numel(x) jitter (rand(n,1) - 0.5) * 0.35; scatter(x(i) jitter, rawData(i,:), 20, [0.25 0.25 0.25], ... filled, MarkerFaceAlpha, 0.5); end ringWidth [];jitter用的是“jitter 幅度 柱宽 0.55 的约 60%”即 ±0.175 再加随机偏差拓展到 0.35。太高会把点甩到相邻柱子的范围里太低则贴在柱中心线上。MarkerFaceAlpha设为 0.5重叠点会自动加深颜色形成视觉上的密度信息。4.3 灰色背景、图片叠加和调用顺序后画的永远在上层灰色背景不是把整个 figure 涂灰而是只改坐标轴区域。图片叠加则有两种情况一种是贴在坐标区外做实验装置示意另一种是嵌入坐标区内部做背景或局部标注。下面这段代码把三种需求一次做完% 灰色背景 网格线弱化 图片叠加到坐标区内 figure(Color, [0.95 0.95 0.95]); % 画布浅灰 ax axes(Parent, gcf, Color, [0.92 0.92 0.92]); hold on; % 网格线用白色弱化存在感 set(ax, XGrid, on, YGrid, on, ... GridColor, [1 1 1], GridAlpha, 0.6); box off; % 先放入一张示意图AlphaData 控制透明度 imgData imread(schematic.png); % 读取当前工作区图片 image([2 4], [5 12], imgData, AlphaData, 0.65); % 再画柱状图和折线图图形对象覆盖在图片之上 bar(x, yMean, 0.55, FaceColor, [0.85 0.45 0.10]); plot(x, yMean, -o, Color, [0 0 0], LineWidth, 1.6);叠加顺序规律很简单后执行的函数默认在上层想调整已画对象的顺序用uistack(obj, bottom)或top。image用imread读入后不关闭句柄后续靠AlphaData控制透明度透明的图片就会透出灰色坐标区底色。图片的坐标范围[2 4]和[5 12]需要手动指定常见做法是先imshow看图片宽高比再按坐标轴数值范围反算放置位置避免图片变形。折线加柱状图同框时折线容易被柱子挡住起始点。我的做法是把柱子FaceColor饱和度降低折线加粗到 1.6 以上并让折线在柱顶之上穿过。如果折线代表趋势、柱状图代表分组均值两者单位通常不同这时应在右侧另起一个 Y 轴用yyaxis right分开而不是硬叠在同一坐标尺上。5. 组合泰勒图和带树状图的环形热图极坐标系下的两套布局5.1 泰勒图先算三个统计量再投影到极坐标组合泰勒图在气象、水文、遥感评估里很常见本质是把观测场和多个模式结果放在同一张图里用“相关系数、标准差、中心 RMSD”三个量对模型做评估。很多 MATLAB 使用者找不到内置taylorplot因为 MATLAB 基础工具箱里没有这个函数常见做法是自己画。泰勒图的极坐标映射是% 多模式泰勒图计算统计量后用 polarscatter 绘制 refSTD 2.1; % 观测场的标准差 modelSTD [1.8 2.4 1.5 2.2]; % 各模式场的标准差 modelCorr [0.92 0.88 0.95 0.82]; % 各模式与观测的空间相关系数 % 映射到极坐标 theta acos(modelCorr); % 相关系数转角度 r modelSTD / refSTD; % 标准差做归一化 figure(Color, w, Position, [100 100 560 520]); pax polaraxes; hold on; polarplot([0 0], [0 1.6], k-, LineWidth, 1.2); % 参考方向线 rlim([0 1.6]); thetaticks([0 30 60 90]); % 90 度方向即相关系数 0 thetaticklabels({1.0,0.87,0.50,0}); % 参考标准差弧线 angles linspace(0, pi/2, 100); polarplot(angles, 1.0 * ones(size(angles)), k--, LineWidth, 1.2); % 绘制各个模式点 polarscatter(theta, r, 80, [0.20 0.35 0.65], filled, MarkerFaceAlpha, 0.8); text(theta, r, {M1,M2,M3,M4}, HorizontalAlignment, center);这段代码的关键是把acos(corr)当作极角把“模式标准差 / 观测标准差”当作半径。当相关系数为 1 时落点角度为 0方向正右相关系数为 0 时角度为 90 度。参考弧线用polarplot画的是半径为 1 的四分之一圆表示模式标准差等于观测标准差时的理想位置。更严格完整的泰勒图还应画出 RMSD 等值线弧实际投稿时需要在图注里写出 RMSD 的归一化公式并给每个点标模式名或序号。5.2 带树状图的环形热图从矩形聚类结果换乘到极坐标带树状图的环形热图是差异基因环形热图、微生物组多样性图里常出现的样式热图圆环一圈代表特征值树状图环在圆环外侧生长。MATLAB 没有现成函数常见做法是先在矩形坐标系里算好聚类树坐标再把线段映射到极坐标。% 环形热图核心逻辑把矩形聚类顺序映射到圆环角度 n 12; % 特征数量 segAngle linspace(0, 2*pi, n1); % 每个扇形块的角度边界 innerR 0.9; % 内半径 outerR 1.3; % 外半径 figure(Color, w, Position, [100 100 600 600]); hold on; for i 1:n % 当前扇形块的四个角点坐标 th linspace(segAngle(i), segAngle(i1), 30); xPoly innerR * cos(th); yPoly innerR * sin(th); % 转外弧再反向闭合 xPoly [xPoly, outerR * flip(cos(th))]; yPoly [yPoly, outerR * flip(sin(th))]; % fill 按顺序填色 fill(xPoly, yPoly, ringColor(i, :), EdgeColor, none); end axis equal off; % 外层树状图把矩形坐标映射到外径之外的环带 nodeXY [ ... ]; % dendrogram 返回的线段端点 outerBand outerR 0.25; % 线性映射示例 thetaMap segAngle;环形热图的工作量其实不在画圆环而在把树状图的分支坐标映射到圆环外侧。以dendrogram返回的 line 对象为例它给出的是矩形坐标系里的(x, y)其中x范围是 0 到叶片数。你要做的只是把这套坐标整体线性移到[0, 2*pi]区间再把y映射成“外半径以外的某段径向距离”。映射公式要做到和热图环的角度边界严格对应否则树状图会整体偏离热图的扇形位置。任何带树状图的环形热图都要过这一关没有捷径。5.3 分组环形热图的径向分块与间距处理分组环形热图是指圆环内部按组别再做切分常见于“组别 A 用内环、组别 B 用外环”这种布局。实现上只需要给半径分段并留出组间空隙参数推荐值作用每组环的厚度0.15~0.25太薄会糊太厚显得空组间角向空隙2~4 度视觉上分离组别不算复杂计算内半径起点0.55~0.8圆心留位给标签或统计量外半径终点1.3~1.6与树状图环带留 0.2 以上距离组间空隙的实现不是让 fill 的扇形少画几度而是把该组的segAngle两端各缩进 1~2 度。缩进的角偏移量对每组一样这样所有空隙在视觉上均匀。圆心区域我通常放一个白色圆盘盖住内部线段再加一句点题说明比如样本数或配色含义。这一步用circle(0,0,innerR)画白圆即可图层放在热图环之后。6. 交付前的图形体检字体、DPI、色差与灰色背景的一致性验证图全部画完之后花最多时间的往往不是构图而是对齐字体、检查色差、导出高清图。我的固定做法是在画图脚本最前面定义全局默认字体和字号% 统一全图字体的全局配置 set(groot, DefaultAxesFontName, Helvetica, ... DefaultAxesFontSize, 9, ... DefaultTextFontName, Helvetica, ... DefaultLegendFontSize, 8, ... DefaultColorbarFontSize, 8);这段配置放在脚本顶部后所有新建的坐标轴、图例、色标都会继承不会出现一个图里宋体黑体混排的情况。导出时用exportgraphics而不用print因为它能按边界裁剪且输出更干净exportgraphics(gcf, figure_final.png, Resolution, 600, ... BackgroundColor, white);关于灰色背景的验证有一个常踩的坑figure(Color, [0.95 0.95 0.95])会把画布整体设为浅灰而坐标轴默认的Color是白色最后导出的图只有坐标区外面一圈灰边内部仍是白底看起来像是渲染出了脏边框。正确做法是让画布背景和坐标轴背景统一或用axes(Color, none)让坐标区透出画布底色。色差检查我给一个轻量思路把导出的 PNG 读回来转成 CIELAB 颜色空间看不同分组色块之间的色差距离。如果两组的b*通道差过小灰度打印后几乎无法区分。没有图像处理工具箱时退而求其次的办法是直接用mat2gray检查颜色矩阵的亮度差保证相邻色块的灰度差在 0.15 以上。任何一组颜色改动后都要在导出分辨率下重新检查因为低 DPI 预览到的颜色过渡在 600 DPI 下会更接近真实印刷效果。最后留一个小技巧用于检查图层重叠用findobj找到当前图上所有带Position属性的对象循环比较其边框是否相交。文字标签和散点重叠是导出后才发现的而这个检查可以把重叠对象的位置偏差打印出来定位到具体是哪个标签和哪个数据点冲突。把这段检查脚本放进validate_figure函数里挂在导出命令之后每次跑图自动校验一遍整个图表里最烦人的人为排查环节才算彻底省掉。本文还有配套的精品资源点击获取
返回列表