1. 为什么二维绘图值得单独拎出来讲
做工程计算和数据分析的人,绕不开MATLAB。很多人学MATLAB的路径都差不多:先学矩阵操作,再学脚本函数,最后卡在“怎么把结果画出来”这一步。我见过太多人,数据算得漂漂亮亮,结果图一出来,自己都不想看第二眼——线太细、字太小、颜色糊成一团、坐标轴范围莫名其妙。更尴尬的是,把这张图发给别人,对方第一句话往往是“这图什么意思?”
二维绘图这件事,看起来简单,实际上藏着大量细节。它不像三维绘图那样有视觉冲击力,也不像App Designer那样能做出花哨界面,但它是日常使用频率最高的功能。一份实验报告、一篇论文、一次项目汇报,最终呈现给别人的往往就是那几张图。图的质量,直接决定了别人对你工作量的判断。
这篇内容适合三类人:第一类是完全没碰过MATLAB绘图的新手,想快速上手画出能看的图;第二类是用过plot但总觉得图不够专业的人,想系统梳理参数体系;第三类是经常需要批量出图的人,想找一套可复用的模板和技巧。我会从最基础的线条控制讲起,一路说到多子图布局、批量导出和常见报错排查,尽量把每个参数背后的逻辑讲清楚,而不是只丢一堆代码让你抄。
需要提前说明的是,下面涉及的所有函数和参数都基于MATLAB的常规版本,不同版本之间可能有细微差异,但核心逻辑是通用的。我用的示例数据都是现场构造的模拟数据,你可以直接复制到自己的脚本里跑。
2. 二维绘图的核心思路与方案选型
2.1 先想清楚“图给谁看”,再决定怎么画
很多人拿到数据第一反应是直接plot(x,y),然后开始调颜色调线宽。这个顺序其实是反的。我的习惯是先在纸上或者脑子里回答三个问题:这张图是给谁看的?对方最关心哪个量?这张图最终会出现在什么载体上?
如果是给自己看的中间过程图,那怎么快怎么来,plot加grid on就够了,甚至不需要标注单位。如果是给同组工程师看的,那重点是把关键参数标清楚,图例、坐标轴单位、峰值位置这些信息不能少。如果是放在正式报告或论文里的图,那就要考虑黑白打印是否还能区分、字号缩小后是否还看得清、导出格式是矢量还是位图。
这个判断直接决定了后面的参数投入。我见过有人给内部讨论用的图花了半小时调字体,也见过有人把论文插图随手截屏贴进去。两种都是浪费。
2.2plot是主干,但别只盯着它
MATLAB二维绘图的函数很多,plot、scatter、bar、stairs、errorbar、area、fill、patch,每个都有自己的适用场景。但实际工作中,plot能覆盖七八成的需求。原因很简单:绝大多数工程数据是连续采样的序列,用线图表达最直观。
不过有几种情况plot会显得别扭。比如数据点很少且需要强调每个点的具体位置,这时候scatter更合适;比如要表达离散类别的数值对比,bar比折线更清楚;比如要展示误差范围,errorbar能直接把置信区间画出来。选错图类型,后面怎么调都别扭。
我的建议是:先把plot的完整参数体系吃透,包括线型、颜色、标记、线宽、标记大小这些。这套体系在scatter、stairs等函数里是相通的。学一套,能迁移到好几个函数上。
2.3 句柄式操作是进阶的分水岭
新手和老手在MATLAB绘图上最大的区别,不是会不会用某个函数,而是懂不懂句柄操作。所谓句柄,就是每个图形对象都有一个“身份证号”,你可以通过这个号去修改它的任意属性。
举个例子。新手改线宽可能是这样写的:
plot(x, y, 'LineWidth', 2);这没问题,但如果后面想再改一次,就得重新画。而用句柄的写法是:
h = plot(x, y); h.LineWidth = 2; h.Color = [0.2 0.4 0.8]; h.LineStyle = '--';好处在哪?你可以先画图,看到效果后再决定怎么调,不用反复重画。更重要的是,当图上有几十条线的时候,你可以用循环批量设置属性,而不是一条一条写参数。这个思路一旦建立起来,后面做复杂图形会轻松很多。
2.4 颜色和线型的搭配有讲究
默认的MATLAB配色其实不差,但问题是当线条超过四条时,默认颜色循环就开始重复,两条线颜色一样,图例就对不上了。这时候需要自己定义颜色序列。
我常用的做法是定义一个颜色矩阵,每行一个RGB值,然后按顺序取用。比如:
colors = [0.00 0.45 0.74; 0.85 0.33 0.10; 0.93 0.69 0.13; 0.49 0.18 0.56; 0.47 0.67 0.19];这组颜色对比度够,打印成灰度也能区分。线型方面,实线、虚线、点线、点划线四种基本够用。但要注意,如果线条很密,虚线看起来会像实线,这时候要么加粗线宽,要么改用颜色区分。
还有一个细节:标记符号不要每条线都加。如果数据点很密,标记会糊成一片。我的习惯是只在关键点或者每隔N个点加标记,用MarkerIndices参数控制。
3. 核心参数体系与实操要点
3.1 线条属性:线宽、颜色、线型
线宽是最容易被忽视但影响最大的参数。默认线宽是0.5磅,在屏幕上看着还行,一打印就细得看不见。我的经验是:屏幕展示用1.5到2,打印用2到3。如果是海报或者PPT投影,可以到3以上。
颜色方面,MATLAB支持几种写法:字符简称(如'r'表示红)、RGB三元组(如[1 0 0])、十六进制(新版本支持)。字符简称方便但选择少,RGB三元组灵活但需要记数值。我建议把常用颜色存成变量,比如c_blue = [0 0.447 0.741],用的时候直接引用,比每次查RGB表快。
线型有四种基本类型:'-'实线、'--'虚线、':'点线、'-.'点划线。选择逻辑是:主要数据用实线,辅助线或参考线用虚线,预测值或拟合值用点线。不要在同一张图里用超过三种线型,否则图例会变得很乱。
这里有个实操技巧:如果两条线趋势接近,光靠颜色区分在黑白打印时会失效,这时候必须配合线型。我通常的做法是“颜色+线型”双重区分,确保任何情况下都能辨认。
3.2 坐标轴控制:范围、刻度、标签
坐标轴范围用xlim和ylim设置。不设置的话MATLAB会自动选一个范围,但自动选的范围往往留白太多或者切掉关键数据。手动设置的原则是:让数据占据画布的主要区域,同时留出少量边距。
刻度用xticks和yticks设置。默认刻度是自动的,但有时候会出现刻度值太长导致重叠,或者刻度间隔不合理。比如时间序列数据,你可能希望每24个点一个刻度,而不是MATLAB自动选的每37个点一个。
标签包括坐标轴名称和单位。这里有个常见错误:只写“时间”不写单位。正确的写法是xlabel('时间 (s)'),单位放在括号里。如果单位有特殊格式,比如m/s^2,可以用xlabel('加速度 (m/s^2)'),MATLAB会自动把^2渲染成上标。
刻度标签的字体大小也要注意。默认是10磅,在缩小后的论文插图里可能看不清。我一般设成12到14,具体看最终图的尺寸。
3.3 图例与标注:位置、内容、样式
图例用legend函数。默认位置是右上角,但右上角经常被数据挡住。可以用'Location'参数指定位置,比如'northwest'、'southeast'、'best'。'best'会让MATLAB自动找一个不挡数据的位置,但计算需要时间,图多的时候会拖慢速度。
图例内容要简洁。不要写“第一条线的数据”这种废话,直接写变量名或物理量。如果变量名有下标,可以用TeX格式,比如legend('v_{in}', 'v_{out}')。
图例的边框可以去掉,用legend('boxoff')。去掉边框后图例更干净,但要注意图例文字和背景的对比度,如果背景是白色,文字用黑色没问题;如果背景有网格线,可能需要给图例加个半透明背景。
标注方面,text函数可以在任意位置加文字,annotation可以加箭头、矩形、椭圆等。我常用的是text加箭头,用来指出峰值或异常点。箭头用annotation('arrow', [x1 x2], [y1 y2]),坐标是归一化的,范围0到1,需要换算一下。
3.4 网格与背景:要不要,怎么要
网格线用grid on打开。但默认的网格线是黑色的,和坐标轴一个颜色,有时候会喧宾夺主。可以用set(gca, 'GridColor', [0.8 0.8 0.8])把网格线调成浅灰色,这样既有参考作用又不抢眼。
背景色默认是白色,一般不需要改。但如果图要放在深色背景的PPT里,可以把背景设成透明,导出时选PNG格式并勾选透明选项。或者直接把背景设成深色,坐标轴和文字改成白色。
这里有个坑:改了背景色之后,导出的图如果格式不支持透明,背景会变成黑色。所以改背景色之前先确认最终用途。
4. 完整实操流程:从数据到成品图
4.1 数据准备与预检查
假设我们有一组模拟的传感器数据,时间从0到10秒,采样间隔0.01秒,信号是两个正弦波的叠加,再加上一点随机噪声。构造代码如下:
t = 0:0.01:10; y1 = sin(2*pi*0.5*t); y2 = 0.5*sin(2*pi*2*t); noise = 0.1*randn(size(t)); y = y1 + y2 + noise;在画图之前,我习惯先做几个检查:数据有没有NaN或Inf?长度是否一致?范围大概是多少?这些检查用summary或简单的min/max就能完成。如果数据里有NaN,画出来的线会断开,这时候要么去掉NaN,要么用fillmissing补上。
4.2 基础绘图与句柄获取
先画一条最简单的线:
figure; h = plot(t, y);这时候图已经出来了,但很粗糙。接下来所有调整都通过h和gca(当前坐标轴句柄)来完成。我习惯把这两个句柄存成变量,后面反复用。
ax = gca;4.3 线条美化:线宽、颜色、透明度
设置线宽和颜色:
h.LineWidth = 1.5; h.Color = [0.00 0.45 0.74];如果想让线条有透明度,MATLAB的plot本身不支持,但可以用patch或fill模拟,或者用line函数配合Color的第四个分量(新版本支持)。不过透明度在工程图里用得不多,除非要叠加很多条线。
4.4 坐标轴精调:范围、刻度、字体
设置坐标轴范围和刻度:
xlim([0 10]); ylim([-2 2]); xticks(0:2:10); yticks(-2:1:2);设置字体和字号:
ax.FontSize = 12; ax.FontName = 'Arial'; ax.LineWidth = 1;注意ax.LineWidth控制的是坐标轴边框的粗细,不是线条的。这个参数经常被忽略,但设成1之后整个图会显得更结实。
4.5 添加图例、标签与标题
xlabel('时间 (s)', 'FontSize', 14); ylabel('幅值 (V)', 'FontSize', 14); title('传感器信号', 'FontSize', 16); legend('原始信号', 'Location', 'northeast', 'Box', 'off');标题不是必须的,如果图下面有图注,标题可以省略。但坐标轴标签一定要有。
4.6 多子图布局与对齐
如果需要在一张图里放多个子图,用subplot或tiledlayout。tiledlayout是新版本推荐的,间距控制更灵活。
tiledlayout(2, 1, 'TileSpacing', 'compact'); nexttile; plot(t, y1); nexttile; plot(t, y2);TileSpacing设为'compact'可以减小子图之间的空白。如果子图共享X轴,可以用linkaxes同步缩放。
4.7 导出与保存:格式、分辨率、尺寸
导出用exportgraphics或print。exportgraphics是新版本推荐的,支持指定分辨率和背景透明。
exportgraphics(gcf, 'figure.png', 'Resolution', 300); exportgraphics(gcf, 'figure.pdf', 'ContentType', 'vector');PNG适合屏幕展示,PDF适合论文投稿。分辨率至少300dpi,如果是线图可以更高。尺寸方面,单栏图一般8到9厘米宽,双栏图17到18厘米宽。可以在exportgraphics里用Width和Height参数指定。
5. 常见问题与排查技巧实录
5.1 图例对不上号怎么办
这是最常见的问题。原因通常是画图时用了循环,但图例是手动写的,顺序错了。解决办法是用句柄数组:
h = gobjects(1, 3); h(1) = plot(x, y1); hold on; h(2) = plot(x, y2); h(3) = plot(x, y3); legend(h, '信号1', '信号2', '信号3');这样图例和线条一一对应,不会错。
5.2 线条太多颜色不够用怎么办
默认颜色循环只有7种左右。超过7条线,要么自定义颜色矩阵,要么用线型区分,要么考虑换一种图类型(比如用imagesc画热力图)。如果非要画很多条线,可以用颜色渐变,比如从蓝到红按顺序取色。
5.3 导出的图模糊怎么办
模糊通常是因为分辨率不够。屏幕截图的分辨率一般只有72到96dpi,而打印需要300dpi以上。用exportgraphics指定Resolution为300或600。如果还是模糊,检查是不是用了saveas,saveas默认分辨率较低。
5.4 中文显示成方框怎么办
这是字体问题。MATLAB默认字体可能不支持中文。解决办法是设置字体为支持中文的,比如'SimHei'或'Microsoft YaHei'。
ax.FontName = 'SimHei';但要注意,如果图要投稿到英文期刊,中文可能不被支持,这时候还是用英文标签。
5.5 图窗大小和导出大小不一致怎么办
figure的Position参数控制屏幕上的大小,exportgraphics的Width和Height控制导出大小。两者可以独立设置。我通常把figure设成合适的大小方便预览,导出时再指定实际尺寸。
5.6 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 线条太细 | 默认线宽0.5 | 设LineWidth为1.5到2 |
| 图例挡住数据 | 默认位置右上 | 用'Location'改位置或'best' |
| 坐标轴刻度重叠 | 刻度太密 | 用xticks手动指定 |
| 导出图模糊 | 分辨率低 | 用exportgraphics设300dpi |
| 中文变方框 | 字体不支持 | 设FontName为中文字体 |
| 多条线颜色重复 | 默认颜色循环用完 | 自定义颜色矩阵 |
| 网格线太抢眼 | 默认黑色 | 设GridColor为浅灰 |
| 子图间距太大 | 默认间距 | 用tiledlayout的TileSpacing |
5.7 几个我踩过的坑
第一个坑:hold on之后忘记hold off,导致后面的图都叠在一起。这个错误很隐蔽,因为图看起来“好像没问题”,直到你发现坐标轴范围不对。
第二个坑:用legend时写了太多条目,图例占了半个图。后来我学会只标关键线条,其他的用文字标注。
第三个坑:导出PDF时用了位图格式,放大后模糊。后来一律用'ContentType', 'vector'导出矢量图。
第四个坑:在循环里反复figure,结果开了几十个窗口,MATLAB卡死。后来改成在循环外开一个figure,循环内用cla清空重画。
6. 批量出图与模板化思路
6.1 把绘图参数抽成配置结构体
如果经常需要画同类型的图,可以把所有参数写成一个结构体,用的时候直接套。
style = struct(); style.LineWidth = 1.5; style.FontSize = 12; style.FontName = 'Arial'; style.Colors = [0.00 0.45 0.74; 0.85 0.33 0.10; 0.93 0.69 0.13]; style.ExportWidth = 8; style.ExportHeight = 6;然后写一个函数,输入数据和配置,输出成品图。这样每次画图只需要改数据,不用重复调参数。
6.2 循环出图时的注意事项
循环出图最大的问题是内存和窗口管理。我的做法是:循环外创建一个figure,循环内用cla清空坐标轴,画完用exportgraphics保存,然后继续下一个。这样始终只有一个窗口,不会卡。
如果数据量很大,可以在循环内加drawnow让MATLAB有机会刷新界面,避免假死。
6.3 用函数封装重复逻辑
比如“画一条带标记的线并设置样式”这个操作,可以封装成函数:
function h = plot_styled(x, y, color, style) h = plot(x, y, 'Color', color, 'LineWidth', 1.5, 'LineStyle', style); end这样主脚本会很干净,修改样式也只需要改一个地方。
7. 一些让图更专业的细节
7.1 去掉多余的边框和刻度
默认的坐标轴是封闭的方框,四个边都有刻度。但很多专业图表只保留左边和下边的轴,右边和上边去掉。用box off可以去掉右边和上边的边框,但刻度还在。要彻底去掉,需要手动设置:
ax.Box = 'off'; ax.XAxis.TickDirection = 'out'; ax.YAxis.TickDirection = 'out';刻度朝外比朝内更清爽,尤其是数据靠近坐标轴的时候。
7.2 用参考线代替网格
如果只是想在某个特定值处加参考,用yline或xline比网格更精准。
yline(0, '--', 'Color', [0.5 0.5 0.5]); xline(5, ':', 'Color', [0.5 0.5 0.5]);参考线用浅灰色虚线,不抢眼但能提供参照。
7.3 颜色搭配的实用原则
不要用纯红纯绿纯蓝,太刺眼。用稍微降低饱和度的颜色,比如[0.85 0.33 0.10]比[1 0 0]舒服。同一张图里颜色不要超过五种,超过就考虑分图。如果必须用很多颜色,用渐变色系,比如从浅蓝到深蓝。
7.4 字体选择的经验
英文用Arial或Helvetica,中文用SimHei或Microsoft YaHei。字号方面,坐标轴标签比刻度大2磅,标题比标签大2磅。比如刻度10,标签12,标题14。这个比例在大多数场景下都合适。
7.5 导出前的最后检查
导出之前,我习惯做三件事:第一,把图缩小到实际尺寸看一遍,确认文字还能看清;第二,打印成黑白看一遍,确认线条还能区分;第三,检查坐标轴单位有没有漏。这三步花不了两分钟,但能避免很多返工。
8. 从二维到多维:什么时候该换工具
二维绘图能解决大部分问题,但有些场景确实不适合。比如数据有三维空间分布,用二维投影会丢失信息;比如要展示随时间变化的二维场,用动画或热力图更合适;比如要交互式探索数据,MATLAB的绘图窗口虽然能缩放平移,但不如专门的交互工具灵活。
不过我的观点是:先把二维绘图做到极致,再考虑其他。因为二维图是基础,三维图、动画、交互界面里的很多概念都是相通的。二维图里的坐标轴控制、颜色映射、图例标注,换到三维里只是多了一个维度,逻辑没变。
如果你发现自己经常需要画三维图,那可以进一步学surf、mesh、scatter3这些函数。但在此之前,把plot的每个参数都试一遍,把句柄操作练熟,把导出流程固定下来,这些投入绝对值得。
我个人在实际操作中的体会是,MATLAB绘图的上限不在于你会多少函数,而在于你对细节的控制力。同样一组数据,有人画出来像草稿,有人画出来像论文插图,差别就在那些看似不起眼的参数上。线宽多0.5,字号大2磅,颜色浅一点,网格淡一点,这些微调累积起来,就是专业和业余的分界线。