Matlab绘图进阶:掌握图形标注、坐标控制与子图布局,绘制专业图表
1. 从“能画”到“画好”:为什么图形辅助操作是Matlab进阶的必修课
很多朋友在刚开始用Matlab画图时,可能都经历过这样一个阶段:用plot、scatter、bar这些基础命令把数据点扔到图上,一看,线是连上了,点也撒上去了,但总觉得哪里不对劲——图看起来“很Matlab”,或者说,很“学生气”。坐标轴范围不合适,曲线挤在一起;图例要么没有,要么位置尴尬;想在一张图里对比好几组数据,结果后画的把先画的给覆盖了;想给论文或者报告配张专业的插图,却不知道如何添加箭头、文本框进行标注。这其实就是从“把图画出来”到“把图画好”之间的一道鸿沟,而跨越这道鸿沟的关键,就在于掌握标题里提到的这四项辅助操作:图形标注、坐标控制、图形保持和图形窗口分割。
我刚开始用Matlab做科研绘图时,也吃了不少亏。导师看着我那默认坐标范围、没有误差棒、图例挤在角落里的图表直摇头,说这图拿出去开会“不专业”。后来花了大量时间摸索,才发现Matlab的绘图引擎其实非常强大,只是它把“画数据”和“装饰图表”这两件事分开了。基础绘图函数负责生成数据的视觉映射,而图的美观性、可读性和信息完整性,则完全依赖于后续这一系列精细的辅助操作。这就像盖房子,plot是砌好了墙,而标注、坐标控制这些就是装修,装修的水平直接决定了房子的最终品质和用途。
掌握这些技能,你的图将不再仅仅是数据的简单呈现,而是会成为清晰、有力、甚至具有说服力的沟通工具。无论是学术论文、工程报告、数据分析简报还是课程作业,一张精心修饰的图表都能让你的工作显得更加严谨和专业。接下来,我就结合自己多年的使用经验,把这四项核心辅助操作掰开揉碎了讲清楚,其中会穿插大量你从官方文档里看不到的实战细节和避坑指南。
2. 图形标注:让你的图表会“说话”
图形标注是给图表添加文字性说明,是传递信息的关键。没有标注的图就像没有字幕的电影,观众只能猜。Matlab提供了从标题、轴标签到图例、文本框、箭头等一整套标注工具。
2.1 基础文本标注:title,xlabel,ylabel,legend
这是最常用的一组函数,但用好它们需要一点技巧。
x = 0:0.1:2*pi; y1 = sin(x); y2 = cos(x); figure; plot(x, y1, ‘r-‘, ‘LineWidth‘, 2); % 画第一条线,红色实线,线宽2 hold on; % 先按下不表,下文详解 plot(x, y2, ‘b--‘, ‘LineWidth‘, 2); % 画第二条线,蓝色虚线,线宽2 title(‘正弦与余弦函数曲线对比‘, ‘FontSize‘, 14, ‘FontWeight‘, ‘bold‘); xlabel(‘时间 / 弧度 (rad)‘, ‘FontSize‘, 12); ylabel(‘函数值‘, ‘FontSize‘, 12); legend({‘sin(x)‘, ‘cos(x)‘}, ‘Location‘, ‘best‘, ‘FontSize‘, 11); grid on; % 添加网格,提高可读性实操心得1:legend的位置玄学‘Location‘参数是图例的灵魂。‘best‘是让Matlab自动找一个遮挡最少的位置,但有时它的“审美”很诡异。我常用的几个可靠选项是:
‘northoutside‘: 放在图的上方外部,特别适合有多条曲线、图例较长的情况,不占用绘图区域。‘eastoutside‘: 放在图的右侧外部,这是论文插图中非常常见的版式,整洁。‘southeast‘: 放在图的右下角内部,如果绘图区域有空白,这是个不错的选择。 永远不要用默认位置或者‘best‘就了事,一定要根据你的图形空白区域手动调整到一个和谐的位置。你可以先用‘best‘,然后通过图形窗口的“编辑图例”工具拖动到满意位置,最后用legend(..., ‘Location‘, [x, y])来固定坐标(这里的[x, y]是归一化坐标,左下角为[0,0],右上角为[1,1])。
实操心得2:中文字体显示问题如果你在标题、标签中使用了中文,很可能会显示为方框。这是因为默认字体不包含中文。一个一劳永逸的解决方法是,在脚本开头或单独的执行命令中设置图形对象的默认字体:
set(0, ‘DefaultAxesFontName‘, ‘SimHei‘); % 设置坐标轴默认字体为黑体 set(0, ‘DefaultTextFontName‘, ‘SimHei‘); % 设置文本默认字体为黑体 % 或者使用系统自带的其他中文字体,如‘Microsoft YaHei‘(雅黑)、‘SimSun‘(宋体)设置后,本会话中创建的所有新图形都会使用该字体。你也可以针对单个文本对象设置:title(‘标题‘, ‘FontName‘, ‘SimHei‘)。
2.2 高级标注:text,annotation与gtext
当需要在图中特定数据点旁添加说明,或者绘制箭头、矩形等形状时,就需要用到高级标注。
text函数:在指定数据坐标处添加文字
x = linspace(0, 10, 100); y = exp(-0.2*x) .* sin(x); plot(x, y); % 找到第一个峰值的大致位置(这里假设我们知道在x≈2.5处) [peakVal, peakIdx] = max(y); x_peak = x(peakIdx); text(x_peak, peakVal, sprintf(‘峰值: %.3f‘, peakVal), ... ‘VerticalAlignment‘, ‘bottom‘, ‘HorizontalAlignment‘, ‘center‘, ... ‘BackgroundColor‘, ‘w‘, ‘EdgeColor‘, ‘k‘, ‘Margin‘, 2);‘VerticalAlignment‘和‘HorizontalAlignment‘控制文本相对于指定坐标(x_peak, peakVal)的对齐方式。‘bottom‘和‘center‘意味着文本的底部中心位于该坐标点。这个组合常用于在数据点上方标注。- 添加背景色(
‘BackgroundColor‘)和边框(‘EdgeColor‘)能让文本在复杂的图中更醒目。
annotation函数:在图形窗口的“归一化坐标”中添加图形对象这是功能更强大的标注工具,可以画箭头、直线、椭圆、矩形、文本框等。它的坐标不是数据坐标,而是相对于整个图形窗口的[0,1]范围。
% 添加一个从点(0.2, 0.8)到点(0.4, 0.6)的箭头(归一化坐标) annotation(‘arrow‘, [0.2, 0.4], [0.8, 0.6], ‘Color‘, ‘r‘, ‘LineWidth‘, 1.5); % 添加一个文本框 annotation(‘textbox‘, [0.15, 0.15, 0.2, 0.1], ‘String‘, ‘重要区域‘, ... ‘FitBoxToText‘, ‘on‘, ‘BackgroundColor‘, ‘yellow‘, ‘EdgeColor‘, ‘none‘);[0.15, 0.15, 0.2, 0.1]表示文本框左下角位于窗口的(0.15, 0.15)位置,宽度为0.2,高度为0.1(归一化单位)。‘FitBoxToText‘, ‘on‘可以让文本框自动调整大小以适应文字,非常实用。
注意:
annotation的坐标是固定的窗口坐标,不会随着你缩放、平移图形而改变。如果你希望标注跟随数据,请使用text函数。annotation更适合添加那些与具体数据无关的说明性标记,比如指向某个区域的箭头、图表的整体注释等。
gtext函数:交互式放置文本这是一个“懒人”但有时很有用的函数。执行gtext(‘请点击放置文字‘)后,图形窗口会等待你用鼠标点击一个位置,然后将文字放在那里。这在需要快速、粗略定位时很方便,但不利于脚本的自动化执行和复现。
3. 坐标控制:驾驭图形的视野与尺度
坐标轴是图表的骨架,控制坐标轴就是控制读者观察数据的“窗口”。不当的坐标范围会扭曲数据呈现,而恰当的设置则能突出关键信息。
3.1 核心控制函数:axis,xlim/ylim,xticks/yticks
axis函数:一键式全局控制axis函数功能强大,通过一个参数就能实现多种控制。
plot(rand(10,1)); axis tight; % 让坐标轴范围紧贴数据范围,不留太多空白 % axis equal; % 使x轴和y轴的刻度单位等长,画圆的时候不会变成椭圆 % axis square; % 使坐标轴区域呈正方形 % axis off; % 关闭所有坐标轴、刻度和标签(常用于图像显示) % axis on; % 打开坐标轴最常用的是axis tight和axis equal。在绘制几何图形或需要保持纵横比时,axis equal至关重要。
xlim,ylim:精确设置范围这是最精细的控制方式。你明确告诉Matlab你想看哪一段数据。
x = 0:0.01:10; y = sin(x) + 0.1*randn(size(x)); % 带噪声的正弦波 plot(x, y); xlim([2, 8]); % 只看x从2到8的部分,相当于“放大镜” ylim([-1.5, 1.5]); % 设置y轴范围,可以突出波动细节在对比多个子图时,统一它们的坐标轴范围是必须的,否则视觉上会产生误导。例如,比较两个不同量级但需要观察变化趋势的数据时,可能需要分别设置ylim;而比较相同物理量的不同实验组时,则必须强制设置相同的ylim。
xticks,yticks,xticklabels,yticklabels:控制刻度与标签这是提升图表专业性的高级技巧。默认的自动刻度可能不理想,比如你希望x轴只显示整数,或者在特定位置显示自定义标签(如类别名称)。
x = 1:5; sales = [100, 150, 120, 200, 180]; bar(x, sales); xticks(1:5); % 确保刻度在1,2,3,4,5的位置 xticklabels({‘Q1‘, ‘Q2‘, ‘Q3‘, ‘Q4‘, ‘Annual‘}); % 设置刻度标签 ylabel(‘销售额 (万元)‘); title(‘季度销售额统计‘);对于时间序列,这个功能尤其有用,可以将数字时间戳转换为可读的日期字符串。
3.2 双y轴与坐标轴比例:yyaxis与semilogy
yyaxis:左右开弓当需要在一张图上对比两个量纲不同、但存在关联的数据序列时,双y轴是标准做法。
x = 0:0.1:10; y1 = sin(x); % 假设是温度(℃) y2 = 50 * cos(x) + 100; % 假设是湿度(%) figure; yyaxis left; % 激活左侧y轴 plot(x, y1, ‘b-‘, ‘LineWidth‘, 2); ylabel(‘温度 (℃)‘, ‘Color‘, ‘b‘); % 标签颜色与曲线对应 ylim([-1.5, 1.5]); yyaxis right; % 激活右侧y轴 plot(x, y2, ‘r--‘, ‘LineWidth‘, 2); ylabel(‘相对湿度 (%)‘, ‘Color‘, ‘r‘); ylim([50, 150]); xlabel(‘时间‘); title(‘温湿度随时间变化曲线‘); grid on;重要提示:使用双y轴时,务必通过颜色、线型等手段清晰区分左右轴的数据,并在图例中明确说明。滥用双y轴可能导致误导性解读,因为它改变了数据的基准线。
对数坐标:semilogy,semilogx,loglog当数据跨越多个数量级时(如信号频谱、微生物数量增长、金融收益率),使用对数坐标可以更清晰地展示变化规律。
f = logspace(0, 5, 1000); % 频率从10^0到10^5 Hz H = 1 ./ (1 + 1j*f/1000); % 一个简单的一阶低通滤波器频率响应 magnitude = abs(H); figure; subplot(2,1,1); semilogx(f, 20*log10(magnitude)); % x轴对数,y轴分贝(也是对数) xlabel(‘频率 (Hz)‘); ylabel(‘增益 (dB)‘); title(‘滤波器幅频响应 (Bode图)‘); grid on; subplot(2,1,2); semilogx(f, angle(H)*180/pi); % 相位 xlabel(‘频率 (Hz)‘); ylabel(‘相位 (度)‘); grid on;semilogx让x轴按对数尺度显示,但坐标值仍然是原始的f。Matlab会自动计算并显示对数刻度。loglog则是两个轴都用对数尺度。
4. 图形保持与覆盖:hold on的智慧与陷阱
hold on命令是Matlab绘图中最基础也最容易出错的概念之一。它的作用是保持当前图形窗口和坐标轴的状态,使后续的绘图命令能在已有的图形上叠加,而不是清空重绘。
4.1hold on的正确使用姿势
x = linspace(0, 2*pi, 100); y_sin = sin(x); y_cos = cos(x); figure; % 创建新图形窗口 plot(x, y_sin, ‘r-‘); % 第一次plot,绘制红色正弦曲线 hold on; % 开启保持状态 plot(x, y_cos, ‘b--‘); % 第二次plot,蓝色虚线余弦曲线叠加在上图 hold off; % 关闭保持状态(这是一个好习惯) title(‘使用hold on叠加图形‘); legend(‘sin(x)‘, ‘cos(x)‘);如果没有hold on,第二条plot命令会清空第一条曲线,只显示余弦曲线。
为什么需要hold off?这是一个编程习惯问题。保持状态是全局的,如果你在一个脚本中打开了hold on,但忘记关闭,那么后续所有针对这个坐标轴的绘图命令都会叠加,可能导致意想不到的混乱。显式地使用hold off就像用完工具后放回原处,让代码更清晰、更安全。另一种更现代、更推荐的方式是直接指定目标坐标轴:
ax = axes; % 创建一个坐标轴对象并获取其句柄 plot(ax, x, y_sin, ‘r-‘); plot(ax, x, y_cos, ‘b--‘); % 直接向同一个坐标轴句柄ax绘图,无需hold on这种方式逻辑更清晰,尤其在处理多个图形窗口和子图时。
4.2hold on的常见“坑”与排查
坑1:属性重置hold on只保持图形内容(线条、散点等),但像xlabel,title,grid这些坐标轴属性,如果在hold on之后再次设置,会正常生效。然而,如果你在hold on后执行了plot(…, ‘Property‘, Value),并希望通过它来改变坐标轴范围,可能会发现不生效,因为hold on状态下,plot会尽量不改变现有坐标轴范围以适应新数据。此时应使用xlim/ylim来强制设置。
坑2:与cla(clear axes) 的混淆有时我们想清空当前坐标轴重新画,错误地使用了hold off; plot(...)。实际上,hold off只是关闭叠加模式,并不会清空已有图形。正确的清空命令是cla。
% 错误示范 plot(x, y1); hold off; % 只是关闭hold,图形还在 plot(x, y2); % 这会清空y1,只画y2,但意图可能是“清空重画” % 正确示范 plot(x, y1); cla; % 清空坐标轴 plot(x, y2); % 画新的图形 % 或者更清晰的 cla reset; % 清空坐标轴并重置所有属性 plot(x, y2);坑3:在循环中滥用在循环中绘图时,如果不加控制地使用hold on,会导致性能下降和图形混乱。
% 低效做法 figure; hold on; for i = 1:100 y = randn(100,1)*i; plot(y); % 每次循环都画一条线,生成100个图形对象 end hold off; % 高效做法:预分配图形对象,或使用‘LineStyle‘, ‘none‘先画点最后连线 % 或者,如果只是看最终结果,可以在循环内计算数据,循环外一次性绘图。5. 图形窗口分割:subplot与tiledlayout的布局艺术
当我们需要并排比较多个相关图形时,分割图形窗口是标准操作。Matlab提供了两种主要工具:经典的subplot和R2019b后引入的更强大的tiledlayout。
5.1 经典工具:subplot(m, n, p)
subplot将图形窗口划分为一个m行n列的网格,并激活第p个子区域进行绘图。p按行优先顺序编号(即先填满第一行,再第二行)。
x = 0:0.1:10; y1 = sin(x); y2 = cos(x); y3 = exp(-0.1*x) .* sin(x); y4 = randn(size(x)); figure(‘Position‘, [100, 100, 1200, 800]); % 设置图形窗口位置和大小 subplot(2, 2, 1); % 2行2列,激活第1块 plot(x, y1); title(‘正弦波‘); grid on; subplot(2, 2, 2); plot(x, y2); title(‘余弦波‘); grid on; subplot(2, 2, 3); plot(x, y3); title(‘衰减正弦波‘); grid on; subplot(2, 2, 4); histogram(y4, 30); % 在第4块画直方图 title(‘随机噪声分布‘); grid on; sgtitle(‘多子图示例‘); % R2018b后可用,为整个图窗添加总标题subplot的局限性:
- 间距死板:子图之间的间距是固定的,调整起来很麻烦,需要通过
subplot(‘Position‘, [left, bottom, width, height])来手动设置每个子图的位置,计算复杂。 - 共享坐标轴困难:虽然可以通过
linkaxes函数链接多个坐标轴的缩放,但设置共享的x轴或y轴标签比较繁琐。 - 颜色栏和图例布局:当子图中包含
colorbar或大型legend时,很容易与其他子图重叠。
5.2 现代布局:tiledlayout与nexttile(推荐)
从R2019b开始,tiledlayout提供了更灵活、更强大的布局控制,彻底解决了subplot的痛点。
x = linspace(0, 2*pi, 200); y1 = sin(x); y2 = cos(x); y3 = sin(x).*cos(x); y4 = sin(x) + 0.1*randn(size(x)); fig = figure(‘Position‘, [100, 100, 1000, 700]); t = tiledlayout(2, 2); % 创建一个2x2的平铺布局 t.TileSpacing = ‘compact‘; % 设置子图间距为‘compact‘, ‘loose‘, 或 ‘none‘ t.Padding = ‘compact‘; % 设置布局与图窗边缘的边距 % 在第一个位置绘图 nexttile; % 自动移动到下一个可用的瓦片(Tile) plot(x, y1, ‘LineWidth‘, 1.5); title(‘正弦函数‘); grid on; nexttile; plot(x, y2, ‘LineWidth‘, 1.5, ‘Color‘, ‘r‘); title(‘余弦函数‘); grid on; nexttile; plot(x, y3, ‘LineWidth‘, 1.5, ‘Color‘, ‘g‘); title(‘乘积函数‘); grid on; nexttile; scatter(x, y4, 10, ‘filled‘); % 散点图 title(‘带噪声的正弦信号‘); grid on; % 为整个布局添加共享标签和总标题 xlabel(t, ‘时间 / 弧度 (rad)‘, ‘FontSize‘, 11); ylabel(t, ‘函数值‘, ‘FontSize‘, 11); title(t, ‘三角函数及其衍生图形‘, ‘FontSize‘, 14, ‘FontWeight‘, ‘bold‘);tiledlayout的核心优势:
- 灵活的间距与边距控制:通过
TileSpacing和Padding属性轻松调整,告别复杂的像素计算。 - 轻松创建跨越多行/列的子图:
t = tiledlayout(3, 3); nexttile([2, 2]); % 这个子图占据2行2列 plot(rand(10,4)); title(‘主图‘); nexttile; % 占据(1,3)位置 plot(rand(5,1)); title(‘小图1‘); nexttile; % 占据(2,3)位置 plot(rand(5,1)); title(‘小图2‘); nexttile([1, 3]); % 这个子图占据第3行,横跨3列 bar(rand(1,5)); title(‘底部长条图‘); - 完美的共享坐标轴:
t = tiledlayout(2,1); ax1 = nexttile; plot(ax1, rand(10,1)); ax2 = nexttile; plot(ax2, rand(10,1)); % 链接x轴,缩放时联动 linkaxes([ax1, ax2], ‘x‘); % 隐藏ax1的x轴刻度标签,使图更紧凑 xticklabels(ax1, {}); xlabel(t, ‘共享的X轴标签‘); % 只在底部添加一个共享标签 - 优雅的Colorbar和Legend布局:
tiledlayout可以为整个布局分配一个colorbar或legend,而不是属于某个特定的子图,自动安排位置避免重叠。t = tiledlayout(1,2); nexttile; contourf(peaks); colorbar; % 这个colorbar只属于第一个子图 nexttile; imagesc(magic(10)); % 如果想为整个布局添加一个colorbar,可以: % cb = colorbar(t); % cb.Layout.Tile = ‘east‘; % 放在布局的右侧
实战选择建议:对于新的项目或脚本,除非有兼容旧版本Matlab的硬性要求,否则一律推荐使用tiledlayout。它的API更现代,布局控制能力远超subplot,能节省大量调整排版的时间。
6. 综合案例:绘制一份专业的数据分析报告图
让我们把前面所有的知识点串联起来,完成一个稍微复杂但很常见的任务:绘制一份包含原始数据、拟合曲线、残差分析以及分布统计的多面板专业图表。
%% 步骤1:生成模拟数据与计算 % 假设我们有一组实验测量数据,并试图用线性模型拟合 x_data = 1:20; y_true = 2.5 * x_data + 1.8; % 真实关系 noise = 5 * randn(size(x_data)); % 加入随机噪声 y_measured = y_true + noise; % 测量值 % 使用polyfit进行一阶(线性)拟合 p = polyfit(x_data, y_measured, 1); % p(1)是斜率,p(2)是截距 y_fitted = polyval(p, x_data); % 计算拟合值 % 计算残差 residuals = y_measured - y_fitted; %% 步骤2:创建图形窗口与布局 fig = figure(‘Position‘, [100, 100, 1400, 800]); % 设定一个较大的窗口 t = tiledlayout(2, 3); % 2行3列布局 t.TileSpacing = ‘compact‘; t.Padding = ‘compact‘; title(t, ‘实验数据线性回归分析报告‘, ‘FontSize‘, 16, ‘FontWeight‘, ‘bold‘); %% 步骤3:绘制主图 (原始数据与拟合线) - 占据左侧两行 ax_main = nexttile([2, 2]); % 跨2行2列 scatter(ax_main, x_data, y_measured, 70, ‘filled‘, ‘MarkerFaceColor‘, [0.2, 0.6, 0.9], ‘MarkerEdgeColor‘, ‘k‘); hold(ax_main, ‘on‘); plot(ax_main, x_data, y_fitted, ‘r-‘, ‘LineWidth‘, 2.5); hold(ax_main, ‘off‘); % 添加标注:拟合方程和R² fit_eqn = sprintf(‘y = %.2fx + %.2f‘, p(1), p(2)); rsq = 1 - sum(residuals.^2) / sum((y_measured - mean(y_measured)).^2); text(ax_main, 0.05, 0.95, {fit_eqn, [‘R^2 = ‘, sprintf(‘%.4f‘, rsq)]}, ... ‘Units‘, ‘normalized‘, ‘VerticalAlignment‘, ‘top‘, ‘FontSize‘, 11, ... ‘BackgroundColor‘, ‘w‘, ‘EdgeColor‘, ‘gray‘); title(ax_main, ‘测量数据与线性拟合‘); xlabel(ax_main, ‘自变量 X‘); ylabel(ax_main, ‘因变量 Y‘); legend(ax_main, {‘测量数据‘, ‘线性拟合‘}, ‘Location‘, ‘northwest‘); grid(ax_main, ‘on‘); ax_main.FontSize = 11; %% 步骤4:绘制残差图 (右上角) ax_resid = nexttile; scatter(ax_resid, x_data, residuals, 40, ‘filled‘, ‘MarkerFaceColor‘, [0.9, 0.4, 0.4]); hold(ax_resid, ‘on‘); % 画一条y=0的参考线 yline(ax_resid, 0, ‘k--‘, ‘LineWidth‘, 1); hold(ax_resid, ‘off‘); title(ax_resid, ‘残差分布‘); xlabel(ax_resid, ‘自变量 X‘); ylabel(ax_resid, ‘残差 (Y_{meas} - Y_{fit})‘); grid(ax_resid, ‘on‘); ax_resid.FontSize = 10; % 检查残差是否随机分布(无趋势) % 可以添加一个趋势线看看 hold(ax_resid, ‘on‘); p_resid_trend = polyfit(x_data, residuals, 1); y_resid_trend = polyval(p_resid_trend, x_data); plot(ax_resid, x_data, y_resid_trend, ‘b:‘, ‘LineWidth‘, 1.2, ‘DisplayName‘, ‘残差趋势‘); hold(ax_resid, ‘off‘); legend(ax_resid, ‘show‘); %% 步骤5:绘制残差直方图 (右中) ax_hist = nexttile; histogram(ax_hist, residuals, 15, ‘FaceColor‘, [0.5, 0.8, 0.5], ‘EdgeColor‘, ‘k‘, ‘Normalization‘, ‘pdf‘); hold(ax_hist, ‘on‘); % 叠加一个正态分布曲线,检查是否服从正态分布 mu = mean(residuals); sigma = std(residuals); x_norm = linspace(min(residuals), max(residuals), 100); y_norm = normpdf(x_norm, mu, sigma); plot(ax_hist, x_norm, y_norm, ‘r-‘, ‘LineWidth‘, 2); hold(ax_resid, ‘off‘); title(ax_hist, ‘残差分布直方图‘); xlabel(ax_hist, ‘残差值‘); ylabel(ax_hist, ‘概率密度‘); legend(ax_hist, {‘残差分布‘, ‘正态分布拟合‘}); grid(ax_hist, ‘on‘); ax_hist.FontSize = 10; %% 步骤6:绘制Q-Q图 (右下) - 检验正态性的另一种方法 ax_qq = nexttile; % 使用统计工具箱中的qqplot,如果没有,可以手动实现或跳过 % 这里假设有统计工具箱 qqplot(ax_qq, residuals); title(ax_hist, ‘残差Q-Q图 (正态性检验)‘); grid(ax_qq, ‘on‘); ax_qq.FontSize = 10; % 调整Q-Q图的标题和标签(qqplot会自动设置,我们覆盖它) title(ax_qq, ‘残差Q-Q图‘); xlabel(ax_qq, ‘标准正态分位数‘); ylabel(ax_qq, ‘残差分位数‘); %% 步骤7:整体美化与输出 % 统一某些坐标轴范围,例如让两个残差分析图的x轴范围与主图对齐(如果需要) linkaxes([ax_main, ax_resid], ‘x‘); % 链接主图和残差图的x轴 xticklabels(ax_resid, {}); % 隐藏残差图的x轴刻度标签,避免重复 % 可以调整一下布局边距 t.Padding = ‘loose‘; % 从‘compact‘改为‘loose‘,让图周围有点空间 % 如果需要保存为高分辨率图片 print(fig, ‘-dpng‘, ‘-r300‘, ‘Linear_Regression_Analysis.png‘); % 保存为300DPI的PNG % print(fig, ‘-dsvg‘, ‘Linear_Regression_Analysis.svg‘); % 保存为矢量图SVG,用于论文通过这个综合案例,你将图形标注(标题、标签、图例、文本框)、坐标控制(linkaxes链接坐标轴、xlim/ylim调整范围)、图形保持(hold on在子图内叠加参考线)以及图形窗口分割(tiledlayout创建复杂布局)全部融合在了一起。这张图的信息密度很高,但布局清晰,每个子图都有明确的职责,共同支撑起“数据线性回归分析”这个主题。这正是一个专业图表该有的样子:不仅仅是展示数据,更是系统地讲述数据背后的故事。