引言
记录一些自己在matlab绘图中的一些设置,首先附上一张个人认为在色彩搭配上比较赏心悦目以及在绘图中构图元素(图例、title、坐标轴名称、刻度名称等)比较完备的。
二维线图
绘图命令模板
首先展示几副个人认为还不错的绘图
ur_color = []; # 如果绘制多条曲线,可以使用RGB三元组(需在0-1之间)或16进制颜色代码
figure;
hold on;
plot(ur_x_data,ur_y_data,'-ok','color',ur_color,'markersize',ur_size,...
'markerfacecolor','ur_color','markeredgecolor',ur_color);
title('') % 设置标题
axis([]); % []内为4/6/8个元素 指定当前坐标区的范围
xlabel(); % 设置x轴坐标名称
xticks(); % 设置x轴坐标值
xticklabels() % 设置x轴刻度标签
ylabel(); % 设置y轴坐标名称
yticks(); % 设置y轴坐标值
xlim([]); % 设置x轴坐标值范围
ylim([]); % 设置y轴坐标值范围
yticklabels(); % 设置y轴刻度标签
legend();添加图例e
set(gca,'linewidth',ur_wdith,'fontsize',ur_size,'') % 设置当前坐标区或图的属性 'fontsize'设置字体大小
下面给出一些可使用名称-值参量指定修改的属性
fontsize
- 字体大小
fontcolor
- 字体颜色
TickDir
- 刻度方向
TickLength
- 刻度长度
xticklabels
、yticklabels
- 设置或查询 x/y 轴刻度标签
注:在plot()
和set(gca,'lindwidth',ur_size)
中都涉及到设置线宽,但设置的是不同图形元素的线宽,前者设置的是绘制的数据线的线宽,后者是坐标轴的线宽。
fill()
函数的使用——为点线图加置信区间
首先上图:
例如有一维向量x、y,分别对应横纵坐标,x_floor为置信区间下限,x_ceiling为上限
plot(x,y) % 首先绘制基础点线图 可以设置颜色线型等参数 此处不再赘述
hold on
% 绘制置信区间
fill([x,fliplr(x)],[y1_floor,fliplr(y1_ceiling)],[0.9490, 0.4745, 0.4392],...
'FaceAlpha',0.2,'EdgeColor', 'none','HandleVisibility', 'off')
% 为了图例中不显示置信区间,有两种方式
% 方式1:
legnd('Data 1','') % 先绘制的是基础数据,第二个绘制的是置信区间,可用空的''跳过图例
% 方式2:即在fill()函数中加入参数-值对——'HandleVisibility', 'off'
参数解释:
fliplr()
函数用于将数组沿列方向左右翻转,如[1 2 3 4 5]翻转为[5 4 3 2 1]
FaceAlpha
参数用于设置透明度,在0~1范围内,值越小透明度越高
EdgeColor
参数用于设置置信度区间的边界线条,none
即不显示
[0.9490, 0.4745, 0.4392]
设置颜色的RGB三元数组 可以替换为任意想要的颜色
为什么需要对数据进行翻转呢? 首先请看fill()
函数的绘制逻辑:
观察数据可发现,它是从(0,0)出发,连接点(4,0)→(5,2)→(2,4)→(1,3)→(0,0),如上图蓝色箭头所示逆时针依次连接形成一个闭环,然后对其内部进行填充。
因此在fill()
函数中第一个参数,即横坐标数据采用[x,fliplr(x)]
这个形式。如x为[1 2 3 4 5],则我们需要构造的形式为[1 2 3 4 5 5 4 3 2 1]。而y只需要将置信区间上下限组合到一起就行,但是上限需要反转一下,即[y1_floor,fliplr(y1_ceiling)]
。
折线图分段赋色
方法一
Case 1
原理:其实就是分段绘制,利用hold on
使多次plot
绘制在一张图上
%% 以横坐标为分割 分段绘制
% 假设y为要绘制的数据 class为对应的标签 如'A' 'B' 'c' 'D/E'
labels = unique(class); %找出不同的标签
colors = ['...';'...';'...']; % 颜色代码 数量不少于标签的种类 也就是想要几个颜色
for i = 2:length(y)
if isequal(class(i),labels(1))
seq = 1;
elseif isequal(class(i),labels(2))
seq = 2;
elseif isequal(class(i),labels(3))
seq = 3;
else
seq = 4;
end
plot(i-1:i,y(i-1:i),'color',colors(seq,:),'linewidth',2);
hold on
end
hold off
优点:省心,不用自己手动找分段的地方
缺点:因为是循环两个数据两个数据的绘制,当数据量非常大时会比较慢,而且生成图后,在图上的操作会很卡。
Case 2
当你明确有或很方便就可以获得每段各自的区间时 直接多次plot
% y - 数据 cut1~cutn - cut为每段的端点
colors = ['...';'...';'...';'...';...];
plot(cut1:cut2,y(cut1:cut2),'color',colors(1,:));
hold on
plot(cut2:cut3,y(cut2:cut3),'color',colors(2,:));
...
plot(...);
% 快速找到需要分段赋色的分隔点
cut = []; % 初始化用于存放分隔点的数组
% y - 数据长度 label - n*1 cell 每个数据点对应的标签
for i = 2:length(y)
if ~strcmp(label{i-1},label{i})
cut = [cut;i];
end
end
添加图例:通常我们添加图例都是在
plot()
行之后添加,但这里如果在绘图循环体外用legend()
添加图例,图窗内图例不正确,图例上每条线段的颜色一样,为第一次循环使用到的颜色。官方文档上这样解释legend命令添加图例:为每个绘制的数据序列创建一个带有描述性标签的图例。因此,笔者猜测是因为底层检测到这是一个数据序列(因为这条线上的每个点都是连接在一起的)。
Case 2 则可以直接使用legend()
正常添加。
针对不能正常添加图例,可以通过单独绘制几条不显示的线,并添加图例达到目的。下面方法二中给出了加图例的方法
方法二
原理:首先绘制原始曲线,通过设置line对象的
Edge
属性来赋色(这个属性我在官方文档中并没有找到有关解释)。
% 绘制原图
hold on
hline = plot(1:length(y),y,'-','linewidth',1.8);
xlabel('时间');ylabel('幅值');
% 绘制图例
hlineset{size(kinds,1)}='';
for i = 1:length(kinds)
hlineset{i} = plot(NaN,NaN,'color',colors(i,:));
end
legend([hlineset{:}],kinds,'AutoUpdate','off');
% 构造颜色列表、修改颜色、绘制辅助线
Xdata=hline.XData;
Cdata=repmat([0,0,0,255],[length(Xdata),1]);
% 绘制辅助分割线
for i =1:length(cut) % 此处的cut是已经找到的分隔点 如上图有五个分隔点
xline(cut(i),'LineWidth',1,'LineStyle','--','Color',[0,0,0]);
end
for i=1:size(kinds,1) % kinds 是数据的标签种类 次数为'A' 'B' 'C' 'D/E'
tBool=find(strcmp(label,kinds{i})); % 找出属于同一类数据的位置索引
Cdata(tBool,1:3)=repmat(colorlist(i,:),[length(tBool),1]);
end
pause(1e-16)
set(hline.Edge,'ColorBinding','interpolated','ColorData',uint8(Cdata)')
set(gca,'LineWidth',1.5,'fontsize',12)
效果如下:
优点:在数据量很大时,也能迅速绘制出来,并且在图上编辑、操作等很流畅。
参考:
[1]MATLAB | 分段赋色折线图及其图例绘制
[2]Matlab 画颜色不同的 分段折线图
三维线图
当多条折线在二维图窗中重叠较多时,可以借助三维线图来展示
%% 生成三个信号
t = 0:0.001:1;
s1 = sin(2*pi*10*t);
s2 = sin(2*pi*10*t) + 0.5*sin(2*pi*20*t);
s3 = 0.7*sin(2*pi*15*t);
z1 = s1 + 0.5*randn(size(t));
z2 = s2 + 0.3*rand(size(t));
z3 = s3 + 0.2*randn(size(t));
% 使三个信号在y方向上相隔一个距离排列,因此生成对应数据长度的y坐标
y1 = zeros(1,length(z1));
y2 = y1 + 1;
y3 = y1 + 2;
%% 开始绘图
clear title %重复绘图时需要清空title
figure
subplot(2,1,1)
plot3(t,y1,z1,'-r')
hold on
plot3(t,y2,z2,'-m')
plot3(t,y3,z3,'-b')
hold off
title = title('EMR');
hXLabel = xlabel('time');
% hYLabel = ylabel('Time');
hZLabel = zlabel('atitude');
set(gca, 'Box', 'off', ... % 边框
'XGrid', 'on', 'YGrid', 'on', 'ZGrid', 'on') % 网格
set(gca, 'FontName', 'Arial','linewidth',1, 'FontSize', 10)
set(gcf,'Color',[1 1 1])
subplot(2,1,2)
hold on
plot(t,z1,'-r')
plot(t,z2,'-m')
plot(t,z3,'-b')
hold off
xlabel('Time')
ylabel('atitude')
legend('signal_1','signal_2','signal_3','NumColumns',3)
% 坐标区调整
set(gca, 'Box', 'off', ... % 边框
'XGrid', 'on', 'YGrid', 'on', 'ZGrid', 'on') % 网格
% 字体字号
set(gca, 'FontName', 'Arial','linewidth',1, 'FontSize', 10)
% set([hXLabel,hZLabel], 'FontName', 'Arial', 'FontSize', 10)
% set(hTitle, 'FontSize', 11, 'FontWeight' , 'bold')
% 背景颜色
set(gcf,'Color',[1 1 1])
柱状图
热图
SCI配色
#8ECFC9 #FFBE7A #FA7F6F #82B0D2 #BEB8DC #E7DAD2
#2878b5 #9ac9db #f8ac8c #c82423 #ff8884
#F27970 #BB9727 #54B345 #32B897 #05B9E2 #8983BF #C76DA2
#A1A9D0 #F0988C #B883D4 #9E9E9E #CFEAF1 #C4A5DE #F6CAE5 #96CCCB
#63b2ee #76da91 #f8cb7f #f89588 #7cd6cf #9192ab
#7898e1 #efa666 #eddd86 #9987ce #63b2ee #76da91
#3b6291 #943c39 #779043 #624c7c #388498 #bf7334
#3f6899 #9c403d #7d9847 #675083 #3b8ba1 #c97937
#002c53 #ffa510 #0c84c6 #ffbd66 #f74d4d #2455a4 #41b7ac
此处附上实现16进制颜色代码转二进制的一个小函数
输入['#F27970';'#BB9727';'#54B345';'#32B897']
输出[242,121,112;187,151,39;84,179,69;50,184,151]
function rgbMatrix = hex2rgb(hexColors)
% 初始化用于存储RGB数组的矩阵,大小和输入的颜色列表大小相同
rgbMatrix = zeros(size(hexColors, 1), 3);
% 遍历每一个十六进制颜色代码
for i = 1:size(hexColors, 1)
% 提取当前颜色代码,并转换为RGB数组
hex = hexColors(i, :);
hex = hex(2:end); % 移除'#'
rgbMatrix(i, :) = [hex2dec(hex(1:2)), hex2dec(hex(3:4)), hex2dec(hex(5:6))];
end
% 如果需要以0到1之间的数表示,可以取消下面的注释
% rgbMatrix = rgbMatrix / 255;
end
注: 配色选取来自科研论文配色【不断更新】 - marsggbo的文章 - 知乎