MATLAB的语法学习曲线很特别:入门时用起来特别简单舒服,但是深入学下去就会感觉到语法非常混乱,无所适从。 尤其在绘图部分,MATLAB杂揉了命令式语句和面向对象的语句,存在太多的语法糖,毫无逻辑性可言。 因此在这里记录一些关于绘图的代码,便于查找。

需要说明的是,下文中的一些代码写法和常见的教程不太一样,包括:

  • 将常见的命令语法都换成了可读性更高的函数语法,例如 hold on 换成 hold('on'),参考官方文档中的 选择命令语法或函数语法
  • 将早期的键值对语法换成了更简洁的形式,例如 plot(x, 'DisplayName', 'energy'); 改成 plot(x, DisplayName = 'energy');

绘制多条曲线

绘制多条曲线

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
x = linspace(0, 2*pi, 100);
y1 = sin(x);
y2 = cos(x);
y3 = sin(2*x);

figure();
hold('on');
plot(x, y1, 'r-', LineWidth=1, DisplayName='sin(x)');
plot(x, y2, 'b--', LineWidth=1, DisplayName='cos(x)');
plot(x, y3, 'g:', LineWidth=1, DisplayName='sin(2x)');
hold('off');

title('Multiple Curves with Direct Legend');

xlabel('x');
ylabel('y');

grid('on');
box('on');
axis('tight');

axis([0 2*pi -1.5 1.5]);
% or xlim([xmin xmax])

legend();

其中

  • LineWidth=1 设置线宽,默认值为 0.5,显得很细;
  • legend() 展示图例:可以在 legend 函数中提供,也可以使用 DisplayName 参数提供;
  • title 设置标题;
  • xlabel, ylabel:设置轴标签;
  • grid('on'):显示网格线;(默认不显示)
  • bxx('on'):显示边框;(默认不显示四条边,只有两个轴会显示)
  • axis('tight'):设置轴的范围紧贴数据范围;(默认可能会有一定的距离)
  • axisxlim / ylim:指定坐标轴范围

plot 曲线样式

plot 函数支持多种曲线样式,包括颜色、线型、标记符号、线宽等,下面记录一下细节。

线型 LineStyle

四种线型如下表

线型 符号 示例
实线 '-' plot(x, y, LineStyle='-')
虚线 '--' plot(x, y, LineStyle='--')
点线 ':' plot(x, y, LineStyle=':')
点划线 '-.' plot(x, y, LineStyle='-.')

颜色 Color

几种标准颜色如下表

颜色 符号 示例
红色 'r' plot(x, y, Color='r')
绿色 'g' plot(x, y, Color='g')
蓝色 'b' plot(x, y, Color='b')
青色 'c' plot(x, y, Color='c')
洋红 'm' plot(x, y, Color='m')
黄色 'y' plot(x, y, Color='y')
黑色 'k' plot(x, y, Color='k')
白色 'w' plot(x, y, Color='w')

除此之外,还可以直接指定 RGB 颜色,例如

1
plot(x, y, Color=[0,0.7,0.9])

R2017a 之后的版本支持通过颜色的第四个通道指定透明度,例如

1
plot(x, y, Color=[0.2,0.5,0.8,0.2])

标记 Marker

几种标记样式如下表

标记 符号 示例
圆圈 'o' plot(x, y, Marker='o')
加号 '+' plot(x, y, Marker='+')
星号 '*' plot(x, y, Marker='*')
'.' plot(x, y, Marker='.')
叉号 'x' plot(x, y, Marker='x')
方块 's' plot(x, y, Marker='s')
菱形 'd' plot(x, y, Marker='d')
向上三角 '^' plot(x, y, Marker='^')
向下三角 'v' plot(x, y, Marker='v')
向左三角 '<' plot(x, y, Marker='<')
向右三角 '>' plot(x, y, Marker='>')
五角星 'p' plot(x, y, Marker='p')
六边形 'h' plot(x, y, Marker='h')

关于 marker,还有如下几个常用属性:

  • 'MarkerSize':标记大小(默认 8),例如 MarkerSize=8
  • 'MarkerEdgeColor':标记边缘颜色,例如 MarkerEdgeColor='k'
  • 'MarkerFaceColor':标记填充颜色(默认不填充),例如MarkerFaceColor='r'
  • 'MarkerIndices':标记显示索引,例如 MarkerIndices=1:5:length(y)

关于 MarkerIndices 的补充说明:如果数据点很多,对每一个点都显示标记符号就显得太拥挤,可以指定需要标记的索引数组,但是 MATLAB 居然没有不支持指定间隔长度设置标记。

调整 marker 样式例如

1
2
3
4
5
6
7
x = linspace(0, 10, 40);
y = sin(x);

figure();
plot(x, y, 'ro', MarkerSize=10, MarkerEdgeColor='b', MarkerFaceColor='y');
grid('on');
title('Customized Markers');

线型 + 颜色 + 标记

由于线型 + 颜色 + 标记这三个属性太常用了,MATLAB支持一次性使用字符数组来配置。

例如

1
plot(x, y, 'r--o');

'r--o' 对应为:

  • Color='r' 红色
  • LineStyle='--' 虚线
  • Marker='o' 圆圈

三者顺序并不固定。

例如

1
2
3
4
5
6
7
8
9
10
11
x = linspace(0, 10, 40);
y1 = sin(x);
y2 = cos(x);

figure();
plot(x, y1, 'ro-'); % 红色 + 圆点 + 实线
hold('on');
plot(x, y2, 'bs--'); % 蓝色 + 方块 + 虚线
hold('off');
legend('sin(x)', 'cos(x)');
grid('on');

LaTeX 支持

MATLAB 绘图窗口支持使用 LaTeX 字体,需要加上参数 Interpreter = 'latex' 进行设置,例如

1
2
3
4
5
6
7
8
9
10
x = linspace(0, 1, 100);
y = sin(2*pi*x);

plot(x, y, 'LineWidth', 1.5);

title('$\sin(2\pi x)$', Interpreter = 'latex');
xlabel('$x$', Interpreter = 'latex');
ylabel('$y$', Interpreter = 'latex');

legend({'$\sin(2\pi x)$'}, Interpreter = 'latex');

显然这里要求系统中已经安装 LaTeX,否则无法使用。

细节调整

使用 grid('on') 可以显示网格线。

下面的写法可以只显示主网格线,关闭次网格线。

1
2
3
4
grid('on');
ax = gca();
ax.XMinorGrid = 'off';
ax.YMinorGrid = 'off';

默认坐标轴会显示主级和次级的坐标,但是有时次级坐标会显得太密集,可以用下面的代码关闭

1
2
3
ax = gca();
ax.XMinorTick = 'off';
ax.YMinorTick = 'off';

关于坐标轴的刻度朝向,MATLAB 默认朝内,可以用下面的命令调整当前绘图窗口的刻度朝向

1
2
3
4
ax = gca();
ax.TickDir = 'in'; % default

ax.TickDir = 'out';

可选值包括:inoutbothnone

注:这里也可以使用 set 函数实现,例如

1
set(gca(), TickDir = 'in', XMinorTick = 'off', ax.YMinorTick = 'off');

对于实际数据范围和坐标轴显示范围,如果没有手动指定,MATLAB 通常会让坐标轴范围略大于数据范围,在两侧留白,但是对于对数坐标轴等可能留白不够明显,可以用下面的两个命令调整

1
2
3
axis('tight');

axis('padded');

绘图窗口保持

默认情况下,绘制的曲线图呈现在一个绘图窗口中,但是再次调用 plot 函数绘图时,MATLAB 会自动清空已打开的绘图窗口,重新绘制。

如果我们在同一窗口中希望把旧图像保持,在此基础上继续绘图,需要使用 hold('on') 命令。hold('on') 命令会使得当前的绘图窗口的内容保持住, 直到使用 hold('off') 命令或者关闭绘图窗口。

例如

1
2
3
4
5
6
7
8
9
10
11
12
x = linspace(0, 2*pi);
y = sin(x);

figure();
plot(x,y)

hold('on')

y2 = cos(x);
plot(x, y2)

hold('off')

但是需要特别注意的是,hold('on') 会影响后续绘图的布局,将其固定为当前布局,例如改为调用对数坐标绘图时,不能先执行 hold('on'),否则轴会被直接固定;

多个绘图窗口

我们可以多次调用 figure(); 语句来创建不同的绘图窗口,分别在其中进行绘图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
x = linspace(0, 30);

% 创建第一个图形窗口并绘制正弦函数
figure();
plot(x, sin(x));
title('Sine');
xlabel('x');
ylabel('sin(x)');

% 创建第二个图形窗口并绘制余弦函数
figure();
plot(x, cos(x));
title('Cosine');
xlabel('x');
ylabel('cos(x)');

多个子图

有很多种方式可以创建子图,下面分别举例。

基于 subplot 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
x = linspace(0, 30);

figure();

subplot(2, 2, 1);
plot(x, sin(x));
title('Sine');

subplot(2, 2, 2);
plot(x, cos(x));
title('Cosine');

subplot(2, 2, 3);
plot(x, tan(x));
title('Tangent');

subplot(2, 2, 4);
plot(x, sec(x));
title('Secant');

sgtitle('Trigonometric Functions');

基于 titledlayout 实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
t = tiledlayout(2,2); % 2*2

title(t,'Trigonometric Functions')
x = linspace(0,30);

nexttile()
plot(x,sin(x))
title('Sine')

nexttile()
plot(x,cos(x))
title('Cosine')

nexttile()
plot(x,tan(x))
title('Tangent')

nexttile()
plot(x,sec(x))
title('Secant')

对数 / 双对数图

plot 不同,可以使用 semilogxsemilogy 把单个坐标轴改成对数坐标,也可以使用 loglog 使用双对数坐标。

1
2
3
4
5
6
7
8
9
10
t = linspace(-1,2,100);
x = 10.^t;
y = x.^2;

figure();
subplot(2,2,1); plot(x,y); title('Linear');
subplot(2,2,2); semilogx(x,y); title('Semilog-x');
subplot(2,2,3); semilogy(x,y); title('Semilog-y');
subplot(2,2,4); loglog(x,y); title('Log-Log');
sgtitle('Coordinate System Comparison');

效果如下图

图像保存与导出

MATLAB提供了很多种保存绘图的方式,需要区分两类保存方式:

  • savefig 代表的保存,得到的是 MATLAB 绘图对象的完整信息,使用 .fig 格式,可以在 MATLAB 中重新加载和编辑图片,但是不能使用图片查看器打开;( fig 格式是 MATLAB 的私有数据格式,与之不同的是,mat 格式是开源的)
  • saveas 代表的导出,导出的是静态图像文件,以通用的图片格式保存,如 PNG、JPEG 等,无法在 MATLAB 中重新编辑。

注意:在常见的图片格式中,pdf,eps,svg 通常是矢量图,png 和 jpg 通常是位图。矢量图是绝对精准的,只有位图才有分辨率的概念。

savefig

使用 savefig 可以直接保存当前绘图窗口到文件中,只需要提供文件名

1
2
3
4
5
6
7
8
9
x = linspace(0, 30);

figure();
plot(x, sin(x));
title('Sine');
xlabel('x');
ylabel('sin(x)');

savefig('demo.fig')

最好指定 figure 句柄进行保存

1
2
3
4
5
6
7
8
9
x = linspace(0, 30);

fig1 = figure();
plot(x, sin(x));
title('Sine');
xlabel('x');
ylabel('sin(x)');

savefig(fig1,'demo.fig')

或者使用 gcf 获取当前绘图窗口句柄并保存

1
2
3
4
5
6
7
8
9
x = linspace(0, 30);

figure();
plot(x, sin(x));
title('Sine');
xlabel('x');
ylabel('sin(x)');

savefig(gcf,'demo.fig')

我们可以在MATLAB中直接点击 .fig 文件来打开它,也可以在代码中使用 openfig 来打开

1
fig = openfig('demo.fig')

saveas

使用 saveas 可以导出为某个具体的图片格式,例如

1
2
3
4
5
6
7
8
9
x = linspace(0, 30);

fig1 = figure();
plot(x, sin(x));
title('Sine');
xlabel('x');
ylabel('sin(x)');

saveas(fig1, 'demo.png');

可以读取 fig 文件并导出图片

1
2
fig = openfig('demo.fig');
saveas(fig, 'demo.png');

注意:

  • 必须为 saveas 函数提供 figure 句柄,可以使用 gcf 获取当前绘图窗口句柄。
  • 导出图片的格式会根据文件后缀名推测,例如 xxx.pngxxx.jpg缺少后缀则会保存为 fig 文件。
  • 这个函数不支持加上一些选项,例如分辨率等,推荐用 exportgraphics 函数替代。

print

print 函数也可以将绘图导出为图片,图片格式必须通过选项传递。

导出 png 格式图片

1
print(fig, 'demo.png', '-dpng');

导出 eps 格式图片

1
print(fig, 'demo.eps', '-depsc');

注意这里必须使用 -depsc 选项才能导出彩色图片,-deps 只能导出黑白图片。

导出 svg 格式图片

1
print(fig, 'demo.svg', '-dsvg');

导出 pdf 格式图片

1
print(fig, 'demo.pdf', '-dpdf');

exportgraphics

对于 R2020a 之后的版本,推荐使用新的 exportgraphics 函数,这个函数可以将 图形(figure)或坐标轴(axes)导出到 EPS、PDF、PNG、JPEG 等格式,是 MATLAB 官方推出的替代旧的 printsaveas 的现代接口。

这个接口比较新,网上并没有太多资料,具体参考 官方文档

导出位图,可以指定分辨率

1
2
exportgraphics(gcf, 'demo.jpg', 'Resolution', 300)
exportgraphics(gcf, 'demo.png', 'Resolution', 600)

导出矢量图

1
exportgraphics(gcf, 'demo.pdf', ContentType='vector')

对于矢量图,通常加上 ContentType='vector' 强制使用矢量图,否则 MATLAB 会自动选择,与之对应的是强制位图 ContentType='image'

这个函数直到 R2025a 才支持 svg 格式的图片导出。

exportgraphics 函数除了可以导出整个 figure,还可以按照坐标轴导出部分图形。

自定义绘图样式

与 matplotlib 一样,MATLAB 提供了接口进行全局层面的默认绘图样式定制,下面是一些例子。

使各种文本默认支持 LaTeX(相当于自动添加 Interpreter = 'latex'

1
2
3
set(groot, 'defaultTextInterpreter', 'latex');
set(groot, 'defaultAxesTickLabelInterpreter', 'latex');
set(groot, 'defaultLegendInterpreter', 'latex');

调整字号和字体

1
2
3
4
5
6
set(groot, 'defaultAxesFontSize', 14);
set(groot, 'defaultTextFontSize', 14);
set(groot, 'defaultLegendFontSize', 12);

set(groot, 'defaultAxesFontName', 'Times New Roman');
set(groot, 'defaultTextFontName', 'Times New Roman');

调整线宽(默认线宽 0.5 太细)、标记大小、坐标轴和刻度线、网格线宽度等

1
2
3
4
set(groot, 'defaultLineLineWidth', 1.0);
set(groot, 'defaultLineMarkerSize', 5);

set(groot, 'defaultAxesLineWidth', 1.0);

让所有坐标轴默认显示边框(相当于自动添加 box('on')

1
set(groot, 'defaultAxesBox', 'on');

设置默认图形渲染器为 painters(矢量渲染),默认通常是 OpenGL,前者导出矢量图质量更好,但是绘图速度会变慢

1
set(groot, 'defaultFigureRenderer', 'painters');

设置 figure 的默认尺寸单位为英寸,以及设置默认 figure 的位置与大小

1
2
set(groot, 'defaultFigureUnits', 'inches');
set(groot, 'defaultFigurePosition', [1 1 6.5 4.5]);

设置图例自动放置在“最好的”位置,默认会倾向于放在右上角。

1
set(groot, 'defaultLegendLocation', 'best');

可以通过如下命令撤销对所有全局默认样式的修改

1
reset(groot)