您当前的位置: 首页 >  matlab

暂无认证

  • 16浏览

    0关注

    93882博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

MATLAB | 绘图复刻(二) | 折线图+误差棒+柱状图+散点抖动+灰色背景+图片叠加

发布时间:2022-10-15 19:00:44 ,浏览量:16

看到gzhR语言ggplot2科研绘图发布了一篇绘图复刻类文章,复刻了: Nature(IF=49.962)文章(Gut microbiota modulates weight gain in mice after discontinued smoke exposure)其中的Figure.1b,绘制效果十分惊艳,手痒就想拿MATLAB也绘制一下试试:

注:数据来自于R语言ggplot2科研绘图

折线图+误差棒+柱状图+散点抖动+灰色背景+图片叠加,要素属实有点多,这篇也会比较长。。

0 绘制效果

原绘制效果绘制效果:

本人复刻效果:

1 数据导入

由于数据不太规整,我们使用readtable读取table格式数据表,之后循环找到我们想要的数据。

Data=readtable('2022.1.15.CSV','VariableNamingRule','preserve'); % 获取各组数据的名称
treatName=unique(Data.treat,'stable'); % 配色数据
colorList=[84,148,206;255,130,131;13,137,138;249,204,82]./255; for i=1:length(treatName) tempData=Data(strcmp(Data.treat,treatName{i}),:); % 将日期数据和value由table转换为array数组
    day=table2array(tempData(:,2)); value=table2array(tempData(:,3:5)); % 后续数据绘图 % ... ... end

配色数据提取的方式很多,可以qq取色或者ppt取色,我公众号上也有一些取色器工具,可以自行查找下载取用,这是图片中用到的配色:

2 基础绘图

在循环内部使用errorbar绘制带误差棒折线图,同时由于误差棒边缘粗细颜色,和最前面折线图不同,因此每组数据还要分别再画两个plot折线图用来绘制粗线条和圆点,这里的误差使用的是SEM误差,即std/sqrt(n):

% ------------------------------------------------------------------------- % 创建图窗并获取坐标区域 figure('Position',[500,200,560,520]) ax=gca;hold on for i=1:length(treatName) tempData=Data(strcmp(Data.treat,treatName{i}),:); % 将日期数据和value由table转换为array数组
    day=table2array(tempData(:,2)); value=table2array(tempData(:,3:5)); % 绘制含误差条的折线图、及粗折线图、及圆点图 errorbar(day,mean(value,2),std(value,1,2)/sqrt(size(value,2)),... 'Color',[0,0,0],'LineWidth',1.8,'Marker','o','CapSize',8); plot(day,mean(value,2),'Color',colorList(i,:),'LineWidth',6) plot(day,mean(value,2),'o','LineWidth',1,'MarkerEdgeColor',[0,0,0],... 'MarkerFaceColor',colorList(i,:),'MarkerSize',9); end

3 生成图例

图像中的图例不是圆点或者直线,而是一个长方形,看起来更像是patch对象的图例,因此需要把循环绘图部分修改一下,创造屏幕外的patch对象用来当作图例的图标,同时将图例的AutoUpdate设置为off以避免后续绘图图例自动更改:

for i=1:length(treatName) tempData=Data(strcmp(Data.treat,treatName{i}),:); % 将日期数据和value由table转换为array数组
    day=table2array(tempData(:,2)); value=table2array(tempData(:,3:5)); % 绘制含误差条的折线图、及粗折线图、及圆点图 errorbar(day,mean(value,2),std(value,1,2)/sqrt(size(value,2)),... 'Color',[0,0,0],'LineWidth',1.8,'Marker','o','CapSize',8); plot(day,mean(value,2),'Color',colorList(i,:),'LineWidth',6) plot(day,mean(value,2),'o','LineWidth',1,'MarkerEdgeColor',[0,0,0],... 'MarkerFaceColor',colorList(i,:),'MarkerSize',9); % 循环生成patch对象用来当作图例的图标 patchHdl(i)=fill([0,0,0,0],[0,0,0,0],colorList(i,:),'LineWidth',1.2); end legend(patchHdl,{'Non\_SMK ','SMK','Non\_SMK+abx','SMK+abx'},'AutoUpdate','off',... 'Location','northoutside','NumColumns',4,'Box','off','FontSize',12) 

4 增添灰色区域和常量线

就是用plot函数绘制直线,使用fill函数画灰色区域,并用uistack函数把这俩放在最下面,这里没用xline画常量线是因为推出较晚(R2018b),且层级关系不好捋顺:

% 绘制区域分隔虚线,这里没用xline是因为推出较晚(R2018b),且层级关系不好捋顺
xLineHdl=plot([21,21],[0,60],'LineWidth',1.8,'LineStyle','--','Color',[0,0,0]); uistack(xLineHdl,'bottom') % 绘制灰色区域并移动到最下方
grayAreaHdl=fill([21,21,40,40],[0+.2,60,60,0+.2],[229,229,229]./255,'EdgeColor','none'); uistack(grayAreaHdl,'bottom') 

5 坐标区域修饰

调整坐标区域字体啊标签啊,横纵坐标比例等一系列元素,详细请看下面代码和注释:

ax=gca; % 调整边缘空间 ax.LooseInset=[0,0,0,0]; % 控制轴范围 ax.YLim=[0,60]; ax.XLim=[0,40]; ax.XTick=0:10:40; ax.YTick=0:20:60; % 修改xy轴标签和字体 ax.XLabel.String='Day'; ax.YLabel.String='Weight change(%)'; ax.XLabel.FontSize=14; ax.YLabel.FontSize=14; ax.XLabel.FontWeight='bold'; ax.YLabel.FontWeight='bold'; % 设置轴线粗细和刻度朝外 ax.LineWidth=1.5; ax.TickDir='out'; 

6 添加显著性标记

提前算好显著性水平后就直接用plot和text添加标记就好了,不是很难:

% 添加显著性标志 plot([36.2,36.2],[18,26],'Color',[0,0,0],'LineWidth',2.5) plot([38,38],[18,40],'Color',[0,0,0],'LineWidth',2.5) text(37.3,22,'***','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(39.3,29,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') 

7 生成子图坐标区域

使用axes函数在当前图窗gcf生成俩新的坐标区域,设置背景色Color为透明none:

% 左上角坐标区域
ax2=axes(gcf,'Position',[.11,.69,.4,.17]); hold on ax2.XLim=[-50,600]; ax2.Color='none'; ax2.LineWidth=1.5; ax2.TickDir='out'; ax2.FontSize=12; ax2.XTick=0:200:600; ax2.YTick=[]; ax2.Title.String='iAUC: Exposure'; ax2.Title.FontWeight='bold'; ax2.Title.FontSize=15; ax2.YDir='reverse'; ax2.YLim=[.4,4.6]; % ------------------------------------------------------------------------- % 右上角坐标区域
ax3=axes(gcf,'Position',[.595,.69,.365,.17]); hold on ax3.XLim=[0,500]; ax3.Color='none'; ax3.LineWidth=1.5; ax3.TickDir='out'; ax3.FontSize=12; ax3.XTick=0:100:500; ax3.YTick=[]; ax3.Title.String='iAUC: Cessation'; ax3.Title.FontWeight='bold'; ax3.Title.FontSize=15; ax3.YDir='reverse'; ax3.YDir='reverse'; ax3.YLim=[.4,4.6]; 

8 柱状图绘制

比如在左侧ax2绘制柱状图,右侧ax3同理,同时因为0基线太细,我们要获取基线的句柄并将其加粗:

% 获取第一组柱状图数据并删除缺失值
barData1=[Data.Non_SMK,Data.SMK,Data.("Non_SMK+abx"),Data.("SMK+abx")]; barData1(isnan(barData1(:,1)),:)=[]; barHdl=barh(ax2,mean(barData1),'FaceColor',[1,1,1],'LineWidth',1.2,'EdgeColor',[0,0,0]); % 设置0基线属性
barBaseLineHdl=barHdl.BaseLine; barBaseLineHdl.LineWidth=1.2; 

9 绘制柱状图误差条

还是使用errorbar函数,不过设置horizontal属性将其变为横向,同时设置LineStyle属性为none隐藏折线部分:

% 绘制误差条 errorbar(ax2,mean(barData1),1:4,std(barData1,1)./sqrt(size(barData1,1)),... 'horizontal','LineStyle','none','LineWidth',1.2,'Color',[0,0,0]) 

10 绘制抖动散点

使用scatter绘制并设置YJitter抖动,不过该属性出现较晚,请使用R2020b及以后版本:

% 绘制抖动散点图 for i=1:4 scatter(ax2,barData1(:,i),i.*ones(1,size(barData1,1)),20,... 'filled','YJitter','density','CData',colorList(i,:)) end

老版本请使用如下方案:

% 老版本方案 % 绘制抖动散点图 for i=1:4 scatter(ax2,barData1(:,i),i+rand(1,size(barData1,1)).*.8-.4,20,... 'filled','CData',colorList(i,:)) end

11 绘制子图显著性标志

还是用plot和text绘制:

% 添加显著性标志 plot(ax2,[370,370],[1,2],'Color',[0,0,0],'LineWidth',2.5) plot(ax2,[530,530],[3,4],'Color',[0,0,0],'LineWidth',2.5) text(ax2,410,1.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(ax2,570,3.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') 

12 子图绘制完整代码
% ========================================================================= % 子图绘制 % 左上角坐标区域
ax2=axes(gcf,'Position',[.11,.69,.4,.17]); hold on ax2.XLim=[-50,600]; ax2.Color='none'; ax2.LineWidth=1.5; ax2.TickDir='out'; ax2.FontSize=12; ax2.XTick=0:200:600; ax2.YTick=[]; ax2.Title.String='iAUC: Exposure'; ax2.Title.FontWeight='bold'; ax2.Title.FontSize=15; ax2.YDir='reverse'; ax2.YLim=[.4,4.6]; % ------------------------------------------------------------------------- % 获取第一组柱状图数据并删除缺失值
barData1=[Data.Non_SMK,Data.SMK,Data.("Non_SMK+abx"),Data.("SMK+abx")]; barData1(isnan(barData1(:,1)),:)=[]; barHdl=barh(ax2,mean(barData1),'FaceColor',[1,1,1],'LineWidth',1.2,'EdgeColor',[0,0,0]); % 设置0基线属性
barBaseLineHdl=barHdl.BaseLine; barBaseLineHdl.LineWidth=1.2; % 绘制误差条 errorbar(ax2,mean(barData1),1:4,std(barData1,1)./sqrt(size(barData1,1)),... 'horizontal','LineStyle','none','LineWidth',1.2,'Color',[0,0,0]) % 绘制抖动散点图 for i=1:4 scatter(ax2,barData1(:,i),i.*ones(1,size(barData1,1)),20,... 'filled','YJitter','density','CData',colorList(i,:)) end % % 老版本方案 % % 绘制抖动散点图 % for i=1:4 % scatter(ax2,barData1(:,i),i+rand(1,size(barData1,1)).*.8-.4,20,... % 'filled','CData',colorList(i,:)) % end % 添加显著性标志 plot(ax2,[370,370],[1,2],'Color',[0,0,0],'LineWidth',2.5) plot(ax2,[530,530],[3,4],'Color',[0,0,0],'LineWidth',2.5) text(ax2,410,1.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(ax2,570,3.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') % ------------------------------------------------------------------------- % 右上角坐标区域
ax3=axes(gcf,'Position',[.595,.69,.365,.17]); hold on ax3.XLim=[0,500]; ax3.Color='none'; ax3.LineWidth=1.5; ax3.TickDir='out'; ax3.FontSize=12; ax3.XTick=0:100:500; ax3.YTick=[]; ax3.Title.String='iAUC: Cessation'; ax3.Title.FontWeight='bold'; ax3.Title.FontSize=15; ax3.YDir='reverse'; ax3.YDir='reverse'; ax3.YLim=[.4,4.6]; % ------------------------------------------------------------------------- % 获取第一组柱状图数据并删除缺失值
barData2=[Data.Non_SMK_1,Data.SMK_1,Data.("Non_SMK+abx_1"),Data.("SMK+abx_1")]; barData2(isnan(barData2(:,1)),:)=[]; barHdl=barh(ax3,mean(barData2),'FaceColor',[1,1,1],'LineWidth',1.2,'EdgeColor',[0,0,0]); % 设置0基线属性
barBaseLineHdl=barHdl.BaseLine; barBaseLineHdl.LineWidth=1.2; % 绘制误差条 errorbar(ax3,mean(barData2),1:4,std(barData2,1)./sqrt(size(barData2,1)),... 'horizontal','LineStyle','none','LineWidth',1.2,'Color',[0,0,0]) % 绘制抖动散点图 for i=1:4 scatter(ax3,barData2(:,i),i.*ones(1,size(barData2,1)),20,... 'filled','YJitter','density','CData',colorList(i,:)) end % % 老版本方案 % % 绘制抖动散点图 % for i=1:4 % scatter(ax3,barData1(:,i),i+rand(1,size(barData2,1)).*.8-.4,20,... % 'filled','CData',colorList(i,:)) % end % 添加显著性标志 plot(ax3,[430,430],[1,2],'Color',[0,0,0],'LineWidth',2.5) plot(ax3,[420,420],[3,4],'Color',[0,0,0],'LineWidth',2.5) text(ax3,465,1.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(ax3,455,3.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') 

完整代码
% @author : slandarer % gzh : slandarer随笔 % zh : 已由hikari更名slandarer Data=readtable('2022.1.15.CSV','VariableNamingRule','preserve'); treatName=unique(Data.treat,'stable'); % 配色数据
colorList=[84,148,206;255,130,131;13,137,138;249,204,82]./255; % ------------------------------------------------------------------------- % 创建图窗获取坐标区域 figure('Position',[500,200,600,580],'Name','slandarer') ax=gca;hold on for i=1:length(treatName) tempData=Data(strcmp(Data.treat,treatName{i}),:); % 将日期数据和value由table转换为array数组
    day=table2array(tempData(:,2)); value=table2array(tempData(:,3:5)); % 绘制含误差条的折线图、及粗折线图、及圆点图 errorbar(day,mean(value,2),std(value,1,2)/sqrt(size(value,2)),... 'Color',[0,0,0],'LineWidth',1.8,'Marker','o','CapSize',8); plot(day,mean(value,2),'Color',colorList(i,:),'LineWidth',6) plot(day,mean(value,2),'o','LineWidth',1,'MarkerEdgeColor',[0,0,0],... 'MarkerFaceColor',colorList(i,:),'MarkerSize',9); % 循环生成patch对象用来当作图例的图标 patchHdl(i)=fill([0,0,0,0],[0,0,0,0],colorList(i,:),'LineWidth',1.2); end legend(patchHdl,{'Non\_SMK ','SMK','Non\_SMK+abx','SMK+abx'},'AutoUpdate','off',... 'Location','northoutside','NumColumns',4,'Box','off','FontSize',12) % ------------------------------------------------------------------------- % 坐标区域修饰 % 调整边缘空间 ax.LooseInset=[0,0,0,0]; % 控制轴范围 ax.YLim=[0,60]; ax.XLim=[0,40]; ax.XTick=0:10:40; ax.YTick=0:20:60; % 修改xy轴标签和字体 ax.XLabel.String='Day'; ax.YLabel.String='Weight change(%)'; ax.XLabel.FontSize=14; ax.YLabel.FontSize=14; ax.XLabel.FontWeight='bold'; ax.YLabel.FontWeight='bold'; % 设置轴线粗细和刻度朝外 ax.LineWidth=1.5; ax.TickDir='out'; % ------------------------------------------------------------------------- % 灰色区域和常量线 % 绘制区域分隔虚线,这里没用xline是因为推出较晚(R2018b),且层级关系不好捋顺
xLineHdl=plot([21,21],[0,60],'LineWidth',1.8,'LineStyle','--','Color',[0,0,0]); uistack(xLineHdl,'bottom') % 绘制灰色区域并移动到最下方
grayAreaHdl=fill([21,21,40,40],[0+.2,60,60,0+.2],[229,229,229]./255,'EdgeColor','none'); uistack(grayAreaHdl,'bottom') % ------------------------------------------------------------------------- % 添加显著性标志 plot([36.2,36.2],[18,26],'Color',[0,0,0],'LineWidth',2.5) plot([38,38],[18,40],'Color',[0,0,0],'LineWidth',2.5) text(37.3,22,'***','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(39.3,29,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') % ========================================================================= % 子图绘制 % 左上角坐标区域
ax2=axes(gcf,'Position',[.11,.69,.4,.17]); hold on ax2.XLim=[-50,600]; ax2.Color='none'; ax2.LineWidth=1.5; ax2.TickDir='out'; ax2.FontSize=12; ax2.XTick=0:200:600; ax2.YTick=[]; ax2.Title.String='iAUC: Exposure'; ax2.Title.FontWeight='bold'; ax2.Title.FontSize=15; ax2.YDir='reverse'; ax2.YLim=[.4,4.6]; % ------------------------------------------------------------------------- % 获取第一组柱状图数据并删除缺失值
barData1=[Data.Non_SMK,Data.SMK,Data.("Non_SMK+abx"),Data.("SMK+abx")]; barData1(isnan(barData1(:,1)),:)=[]; barHdl=barh(ax2,mean(barData1),'FaceColor',[1,1,1],'LineWidth',1.2,'EdgeColor',[0,0,0]); % 设置0基线属性
barBaseLineHdl=barHdl.BaseLine; barBaseLineHdl.LineWidth=1.2; % 绘制误差条 errorbar(ax2,mean(barData1),1:4,std(barData1,1)./sqrt(size(barData1,1)),... 'horizontal','LineStyle','none','LineWidth',1.2,'Color',[0,0,0]) % 绘制抖动散点图 for i=1:4 scatter(ax2,barData1(:,i),i.*ones(1,size(barData1,1)),20,... 'filled','YJitter','density','CData',colorList(i,:)) end % % 老版本方案 % % 绘制抖动散点图 % for i=1:4 % scatter(ax2,barData1(:,i),i+rand(1,size(barData1,1)).*.8-.4,20,... % 'filled','CData',colorList(i,:)) % end % 添加显著性标志 plot(ax2,[370,370],[1,2],'Color',[0,0,0],'LineWidth',2.5) plot(ax2,[530,530],[3,4],'Color',[0,0,0],'LineWidth',2.5) text(ax2,410,1.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(ax2,570,3.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') % ------------------------------------------------------------------------- % 右上角坐标区域
ax3=axes(gcf,'Position',[.595,.69,.365,.17]); hold on ax3.XLim=[0,500]; ax3.Color='none'; ax3.LineWidth=1.5; ax3.TickDir='out'; ax3.FontSize=12; ax3.XTick=0:100:500; ax3.YTick=[]; ax3.Title.String='iAUC: Cessation'; ax3.Title.FontWeight='bold'; ax3.Title.FontSize=15; ax3.YDir='reverse'; ax3.YDir='reverse'; ax3.YLim=[.4,4.6]; % ------------------------------------------------------------------------- % 获取第一组柱状图数据并删除缺失值
barData2=[Data.Non_SMK_1,Data.SMK_1,Data.("Non_SMK+abx_1"),Data.("SMK+abx_1")]; barData2(isnan(barData2(:,1)),:)=[]; barHdl=barh(ax3,mean(barData2),'FaceColor',[1,1,1],'LineWidth',1.2,'EdgeColor',[0,0,0]); % 设置0基线属性
barBaseLineHdl=barHdl.BaseLine; barBaseLineHdl.LineWidth=1.2; % 绘制误差条 errorbar(ax3,mean(barData2),1:4,std(barData2,1)./sqrt(size(barData2,1)),... 'horizontal','LineStyle','none','LineWidth',1.2,'Color',[0,0,0]) % 绘制抖动散点图 for i=1:4 scatter(ax3,barData2(:,i),i.*ones(1,size(barData2,1)),20,... 'filled','YJitter','density','CData',colorList(i,:)) end % % 老版本方案 % % 绘制抖动散点图 % for i=1:4 % scatter(ax3,barData1(:,i),i+rand(1,size(barData2,1)).*.8-.4,20,... % 'filled','CData',colorList(i,:)) % end % 添加显著性标志 plot(ax3,[430,430],[1,2],'Color',[0,0,0],'LineWidth',2.5) plot(ax3,[420,420],[3,4],'Color',[0,0,0],'LineWidth',2.5) text(ax3,465,1.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') text(ax3,455,3.5,'****','Rotation',90,'FontSize',17,'HorizontalAlignment','center','FontWeight','bold') 

【链接】:https://pan.baidu.com/s/1L3VpjMGkdCQ6ljEZxQxGiQ?pwd=slan 【提取码】:slan

关注
打赏
1655516835
查看更多评论
立即登录/注册

微信扫码登录

1.2093s