【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

这篇具有很好参考价值的文章主要介绍了【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


有时候,用MATLAB绘制坐标图时会出现有的曲线值都特别大,有的曲线值都很小,但是又想在同一幅图中将他们展示出来,于是需要截断坐标轴的刻度或者改变纵轴的刻度,使其不均匀。此时,就需要对横坐标或纵坐标进行截断。

1 方法一

参考:博客-MATLAB实例:截断坐标轴(Broken Axis)

1.1 原始图形

MATLAB相关代码如下:

clear; 
clc;
close all;
%% 原始图片
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
x_min = 0.1;            % 横坐标刻度最小值
x_interval = 0.1;      % 横坐标刻度间隔距离
x_max = 1;              % 横坐标刻度最大值
 
%% 绘图
X = x_min:x_interval:x_max;
h = plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Original image.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

1.2 截断横坐标

MATLAB相关代码如下:

clear; 
clc; 
close all;
%% 横轴截断后图像
% 数据
format short g
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
%% 参数设置
x_min = 0.1;            % 横轴刻度最小值
x_interval = 0.1;       % 横坐标两个刻度间隔距离
x_break_start = 0.5; % 截断的开始值
x_break_end = 0.9;  % 截断的结束值
 
x_break_end = x_break_end-x_interval;
x_max = length(data(1, :))*x_interval+x_min-x_interval; %横轴刻度最大值
X = x_min:x_interval:x_max;
adjust_value=0.4*x_interval; %微调截断处x坐标
 
% 超过截断结束位置的那些曲线统统向左平移uptate_num个长度
data(:, find(abs(X-x_break_start)<eps)+1:(end-round((x_break_end-x_break_start)/x_interval)))=data(:, X>x_break_end+eps);
 
x_max_new=x_max-x_break_end+x_break_start;
X=x_min:x_interval:x_max_new;
new_range=round(x_max_new/x_interval);

%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, 1:new_range), 'k*-', X, data(2, 1:new_range), 'g^-', X, data(3, 1:new_range), 'r-s', X, data(4, 1:new_range), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);

set(gcf,'color','w') %后面背景变白
xlim([x_min x_max_new]); %横坐标范围
xlabel('X');
ylabel('Y');
 hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);

% 横坐标截断设置
xlimit=get(gca,'xlim');
location_X=(x_break_start+adjust_value-xlimit(1))/diff(xlimit);
t1=text(location_X, 0,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
t2=text(location_X, 1,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
 
% 重新定义横坐标刻度
xtick=x_min:x_interval:x_max_new;
set(gca,'xtick',xtick);
xtick(xtick>x_break_start+eps)=xtick(xtick>x_break_start+eps)+x_break_end-x_break_start;
for i=1:length(xtick)
   xticklabel{i}=sprintf('%.1f',xtick(i));
end
set(gca,'xTickLabel', xticklabel, 'FontSize', 12, 'FontName', 'Times New Roman');   %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_X_Axis.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

1.3 截断纵坐标

MATLAB相关代码如下:

clear; 
clc; 
close all;
%% 纵轴截断后图像
% 数据
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
y_interval=1;  %纵坐标两个刻度间隔距离
y_max=11; %纵轴刻度最大值
y_break_start=4; % 截断的开始值
y_break_end=9; % 截断的结束值
 
X=x_min:x_interval:x_max;
adjust_value=0.4*y_interval; %微调截断处y坐标
uptate_num=y_break_end-y_break_start-y_interval; %最高处曲线向下平移大小
 
% 超过截断结束位置的那些曲线统统向下平移uptate_num个长度
for i=1:length(data(:, 1))
    if data(i, :)>y_break_end
        data(i, :)=data(i, :)-uptate_num;
    end
end
 
%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
 
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
 
% 纵坐标截断设置
ylimit=get(gca,'ylim');
location_Y=(y_break_start+adjust_value-ylimit(1))/diff(ylimit);
t1=text(0, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t1,'rotation',90);
t2=text(1, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t2,'rotation',90);
 
% 重新定义纵坐标刻度
ytick=0:y_interval:y_max;
set(gca,'ytick',ytick);
ytick(ytick>y_break_start+eps)=ytick(ytick>y_break_start+eps)+uptate_num;
for i=1:length(ytick)
   yticklabel{i}=sprintf('%d',ytick(i));
end
set(gca,'yTickLabel', yticklabel, 'FontSize', 12, 'FontName', 'Times New Roman'); %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_Y_Axis.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

1.4 截断横纵坐标

MATLAB相关代码如下:

clear; 
clc; 
close all;
%% 横轴截断后图像
% 数据
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
%% 参数设置
x_min=0.1; %横轴刻度最小值
x_interval=0.1;  %横坐标两个刻度间隔距离
x_break_start=0.5; % 截断的开始值
x_break_end=0.9; % 截断的结束值
y_interval=1;  %纵坐标两个刻度间隔距离
y_max=11; %纵轴刻度最大值
y_break_start=4; % 截断的开始值
y_break_end=9; % 截断的结束值
 
x_break_end=x_break_end-x_interval;
x_max=length(data(1, :))*x_interval+x_min-x_interval; %横轴刻度最大值
X=x_min:x_interval:x_max;
adjust_value_x=0.4*x_interval; %微调截断处x坐标
adjust_value_y=0.4*y_interval; %微调截断处y坐标
uptate_num=y_break_end-y_break_start-y_interval; %最高处曲线向下平移大小
 
% 超过截断结束位置的那些曲线统统向左平移uptate_num个长度
data(:, find(abs(X-x_break_start)<eps)+1:(end-round((x_break_end-x_break_start)/x_interval)))=data(:, X>x_break_end+eps);
% 超过截断结束位置的那些曲线统统向下平移uptate_num个长度
for i=1:length(data(:, 1))
    if data(i, :)>y_break_end
        data(i, :)=data(i, :)-uptate_num;
    end
end
 
x_max_new=x_max-x_break_end+x_break_start;
X=x_min:x_interval:x_max_new;
new_range=round(x_max_new/x_interval);
%% 绘图
% 根据曲线的个数进行修改,这里曲线是4条
h=plot(X, data(1, 1:new_range), 'k*-', X, data(2, 1:new_range), 'g^-', X, data(3, 1:new_range), 'r-s', X, data(4, 1:new_range), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
 
set(gcf,'color','w') %后面背景变白
xlim([x_min x_max_new]); %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4);
 
% 横坐标截断设置
xlimit=get(gca,'xlim');
location_X=(x_break_start+adjust_value_x-xlimit(1))/diff(xlimit);
t1=text(location_X, 0,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
t2=text(location_X, 1,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
 
% 重新定义横坐标刻度
xtick=x_min:x_interval:x_max_new;
set(gca,'xtick',xtick);
xtick(xtick>x_break_start+eps)=xtick(xtick>x_break_start+eps)+x_break_end-x_break_start;
for i=1:length(xtick)
   xticklabel{i}=sprintf('%.1f',xtick(i));
end
 
% 纵坐标截断设置
ylimit=get(gca,'ylim');
location_Y=(y_break_start+adjust_value_y-ylimit(1))/diff(ylimit);
t1=text(0, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t1,'rotation',90);
t2=text(1, location_Y,'//','sc','BackgroundColor','w','margin',eps, 'fontsize',13);
set(t2,'rotation',90);
 
% 重新定义纵坐标刻度
ytick=0:y_interval:y_max;
set(gca,'ytick',ytick);
ytick(ytick>y_break_start+eps)=ytick(ytick>y_break_start+eps)+uptate_num;
for i=1:length(ytick)
   yticklabel{i}=sprintf('%d',ytick(i));
end
set(gca,'xTickLabel', xticklabel, 'yTickLabel', yticklabel, 'FontSize', 12, 'FontName', 'Times New Roman'); %修改坐标名称、字体
text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
saveas(gcf,sprintf('Break_X_Y_Axis.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

2 方法二

mathworks官网代码:
截断横坐标-Break X Axis
截断纵坐标-Break Y Axis

2.1 截断横坐标

2.1.1 案例

MATLAB相关代码如下:

clear; 
clc; 
close all;
%% 纵轴截断后图像
% 数据
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
 
X=x_min:x_interval:x_max;
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
 
set(gcf,'color','w')        %后面背景变白

xlim([x_min x_max]);    %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4,'color','k');
% text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
%% 调用已有的代码,两个函数只能调用一个,不能同时调用,出错
% breakyaxis([4 9]);  % 截断纵坐标
breakxaxis([0.5 0.9]);  %截断横坐标

saveas(gcf,sprintf('Other_Break_Axis.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

2.1.2 调用函数

调用代码:

breakyaxis([minXvalue,maxXvalue])

函数代码:

% breakxaxes splits data in an axes so that data is in a left and right pane.
%
%   breakXAxes(splitXLim) splitXLim is a 2 element vector containing a range
%   of x values from splitXLim(1) to splitXLim(2) to remove from the axes.
%   They must be within the current xLimis of the axes.
%
%   breakXAxes(splitXLim,splitWidth) splitWidth is the distance to 
%   seperate the left and right side.  Units are the same as 
%   get(AX,'uints') default is 0.015
% 
%   breakXAxes(splitXLim,splitWidth,yOverhang) yOverhang stretches the 
%   axis split graphic to extend past the top and bottom of the plot by
%   the distance set by YOverhang.  Units are the same as get(AX,'units')
%   default value is 0.015
%
%   breakXAxes(AX, ...) performs the operation on the axis specified by AX
%
function breakInfo = breakxaxis(varargin)

    %Validate Arguements
    if nargin < 1 || nargin > 4
       error('Wrong number of arguements'); 
    end

    if isscalar(varargin{1}) && ishandle(varargin{1})
        mainAxes = varargin{1};
        argOffset = 1;
        argCnt = nargin - 1;
        if ~strcmp(get(mainAxes,'Type'),'axes')
           error('Handle object must be Type Axes'); 
        end
    else
        mainAxes = gca;
        argOffset = 0;
        argCnt = nargin;
    end
    
    if (strcmp(get(mainAxes,'XScale'),'log'))
        error('Log X Axes are not supported'); 
    end
    
    if (argCnt < 3)
        yOverhang = 0.015;
    else
        yOverhang = varargin{3 + argOffset};
        if  numel(yOverhang) ~= 1 || ~isreal(yOverhang) || ~isnumeric(yOverhang)
            error('YOverhang must be a scalar number');
        elseif (yOverhang < 0)
            error('YOverhang must not be negative');
        end
        yOverhang = double(yOverhang);
    end
    
    if (argCnt < 2)
        splitWidth = 0.015;
    else
        splitWidth = varargin{2 + argOffset};
        if  numel(yOverhang) ~= 1 || ~isreal(yOverhang) || ~isnumeric(yOverhang)
            error('splitWidth must be a scalar number');
        elseif (yOverhang < 0)
            error('splitWidth must not be negative');
        end
        splitWidth = double(splitWidth);
    end
    
    splitXLim = varargin{1 + argOffset};
    if numel(splitXLim) ~= 2 || ~isnumeric(splitXLim) || ~isreal(yOverhang)
       error(splitXLim,'Must be a vector length 2');
    end
    splitXLim = double(splitXLim);
    
    mainXLim = get(mainAxes,'XLim');
    if (any(splitXLim >= mainXLim(2)) || any(splitXLim <= mainXLim(1)))
       error('splitXLim must be in the range given by get(AX,''XLim'')');
    end
    
    mainPosition = get(mainAxes,'Position');
    if (splitWidth > mainPosition(3) ) 
       error('Split width is too large') 
    end
   
    %We need to create 4 axes
    % leftAxes - is used for the left x axis and left pane data
    % rightAxes - is used to the right x axis and right pane data
    % annotationAxes - is used to display the y axis and title
    % breakAxes - this is an axes with the same size and position as main
    %   is it used to draw a seperator between the left and right side
    

    %Grab Some Parameters from the main axis (e.g the one we are spliting)
    mainXLim = get(mainAxes,'XLim');
    mainYLim = get(mainAxes,'YLim');
    mainPosition = get(mainAxes,'Position');
    mainParent = get(mainAxes,'Parent');
    mainWidth = mainPosition(3); %Positions have the format [left bottom width height]
    %mainXRange = mainXLim(2) - mainXLim(1);
    mainFigure = get(mainAxes,'Parent');
    mainYColor = get(mainAxes,'YColor');
    mainLineWidth = get(mainAxes,'LineWidth');
    figureColor = get(mainFigure,'Color');
    mainYTickLabelMode = get(mainAxes,'YTickLabelMode');
    mainXLabel = get(mainAxes,'XLabel');
    mainXDir = get(mainAxes,'XDir');
    mainLayer = get(mainAxes,'Layer');
    
    %Save Main Axis Z Order
    figureChildren = get(mainFigure,'Children');
    zOrder = find(figureChildren == mainAxes);
    
    %Calculate where axesLeft and axesRight will be layed on screen
    %And their respctive XLimits
    leftXLimTemp = [mainXLim(1) splitXLim(1)];
    rightXLimTemp = [splitXLim(2) mainXLim(2)];

    leftXRangeTemp = leftXLimTemp(2) - leftXLimTemp(1);
    rightXRangeTemp = rightXLimTemp(2) - rightXLimTemp(1);

    leftWidthTemp = leftXRangeTemp / (leftXRangeTemp + rightXRangeTemp) * (mainWidth - splitWidth);
    rightWidthTemp = rightXRangeTemp / (leftXRangeTemp + rightXRangeTemp) * (mainWidth - splitWidth);

    leftStretch = (leftWidthTemp + splitWidth/2) / leftWidthTemp;
    leftXRange = leftXRangeTemp * leftStretch;
    leftWidth = leftWidthTemp * leftStretch;

    rightStretch = (rightWidthTemp + splitWidth/2) / rightWidthTemp;
    rightXRange = rightXRangeTemp * rightStretch;
    rightWidth = rightWidthTemp * rightStretch;
    
    leftXLim = [mainXLim(1) mainXLim(1)+leftXRange];
    rightXLim = [mainXLim(2)-rightXRange mainXLim(2)];
    
    if (strcmp(mainXDir, 'normal')) 
        leftPosition = mainPosition;
        leftPosition(3) = leftWidth; 

        rightPosition = mainPosition;
        rightPosition(1) = mainPosition(1) + leftWidth;
        rightPosition(3) = rightWidth;
    else
        %Left Axis will actually go on the right side a vise versa
        rightPosition = mainPosition;
        rightPosition(3) = rightWidth; 

        leftPosition = mainPosition;
        leftPosition(1) = mainPosition(1) + rightWidth;
        leftPosition(3) = leftWidth;
    end
 
    %Create the Annotations layer, if the Layer is top, draw the axes on
    %top (e.g. after) drawing the left and right pane
    if strcmp(mainLayer,'bottom')
        annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
    end
    
    %Create and position the leftAxes. Remove all Y Axis Annotations, the 
    %title, and a potentially offensive tick mark 
    leftAxes = copyobj(mainAxes,mainParent);
    set(leftAxes,'Position', leftPosition, ...
        'XLim', leftXLim, ...
        'YLim', mainYLim, ...
        'YGrid' ,'off', ...
        'YMinorGrid', 'off', ...
        'YMinorTick','off', ...
        'YTick', [], ...
        'YTickLabel', [], ...
        'box','off');
    if strcmp(mainLayer,'bottom')
        set(leftAxes,'Color','none');
    end
    delete(get(leftAxes,'YLabel')); 
    delete(get(leftAxes,'XLabel'));
    delete(get(leftAxes,'Title'));
    
    if strcmp(mainYTickLabelMode,'auto')
        xTick =  get(leftAxes,'XTick');
        set(leftAxes,'XTick',xTick(1:(end-1)));
    end
    
    %Create and position the rightAxes. Remove all Y Axis annotations, the 
    %title, and a potentially offensive tick mark 
    rightAxes = copyobj(mainAxes,mainParent);
    set(rightAxes,'Position', rightPosition, ...
        'XLim', rightXLim, ...
        'YLim', mainYLim, ...
        'YGrid' ,'off', ...
        'YMinorGrid', 'off', ...
        'YMinorTick','off', ...
        'YTick', [], ...
        'YTickLabel', [], ...
        'box','off');
    if strcmp(mainLayer,'bottom')
        set(rightAxes,'Color','none');
    end
    delete(get(rightAxes,'YLabel')); 
    delete(get(rightAxes,'XLabel'));
    delete(get(rightAxes,'Title'));
    
    if strcmp(mainYTickLabelMode,'auto')
        xTick =  get(rightAxes,'XTick');
        set(rightAxes,'XTick',xTick(2:end));
    end

        %Create the Annotations layer, if the Layer is top, draw the axes on
    %top (e.g. after) drawing the left and right pane
    if strcmp(mainLayer,'top')
        annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent);
        set(annotationAxes, 'Color','none');
    end
    
    %Create breakAxes, remove all graphics objects and hide all annotations
    breakAxes = copyobj(mainAxes,mainParent);
    children = get(breakAxes,'Children');
    for i = 1:numel(children)
       delete(children(i)); 
    end
    
    set(breakAxes,'Color','none');
    %Stretch the breakAxes vertically to cover the horzontal axes lines
    orignalUnits = get(breakAxes,'Units');
    set(breakAxes,'Units','Pixel');
    breakPosition = get(breakAxes,'Position');
    nudgeFactor = get(breakAxes,'LineWidth');
    breakPosition(4) = breakPosition(4) +  nudgeFactor;
    set(breakAxes,'Position',breakPosition);
    set(breakAxes,'Units',orignalUnits);

    %Stretch the breakAxes vertically to create an overhang for sylistic
    %effect
    breakPosition = get(breakAxes,'Position');
    breakPosition(2) = breakPosition(2) - yOverhang;
    breakPosition(4) = breakPosition(4) +  2*yOverhang;
    set(breakAxes,'Position',breakPosition);
    
    %Create a sine shaped patch to seperate the 2 sides
    breakXLim = [mainPosition(1) mainPosition(1)+mainPosition(3)];
    set(breakAxes,'xlim',breakXLim);
    theta = linspace(0,2*pi,100);
    yPoints = linspace(mainYLim(1),mainYLim(2),100);
    amp = splitWidth/2 * 0.9;
    xPoints1 = amp * sin(theta) + mainPosition(1) + leftWidthTemp;
    xPoints2 = amp * sin(theta) + mainPosition(1) + mainPosition(3) - rightWidthTemp;
    patchPointsX = [xPoints1 xPoints2(end:-1:1) xPoints1(1)];
    patchPointsY = [yPoints  yPoints(end:-1:1)  yPoints(1)];
    patch(patchPointsX,patchPointsY ,figureColor,'EdgeColor',figureColor,'Parent',breakAxes);

    %Create A Line To Delineate the left and right edge of the patch
    line('xData',xPoints1,'ydata',yPoints,'Parent',breakAxes,'Color',mainYColor,'LineWidth',mainLineWidth);
    line('xData',xPoints2,'ydata',yPoints,'Parent',breakAxes,'Color',mainYColor,'LineWidth',mainLineWidth);

    set(breakAxes,'Visible','off');
    
    %Make the old main axes invisiable
    invisibleObjects = RecursiveSetVisibleOff(mainAxes);

    %Preserve the z-order of the figure
    uistack([leftAxes rightAxes breakAxes annotationAxes],'down',zOrder-1)
    
    %Set the rezise mode to position so that we can dynamically change the
    %size of the figure without screwing things up
    set([leftAxes rightAxes breakAxes annotationAxes],'ActivePositionProperty','Position');
 
    %Playing with the titles labels etc can cause matlab to reposition
    %the axes in some cases.  Mannually force the position to be correct. 
    set([breakAxes annotationAxes],'Position',mainPosition);
    
    %Save the axes so we can unbreak the axis easily
    breakInfo = struct();
    breakInfo.leftAxes = leftAxes;
    breakInfo.rightAxes = rightAxes;
    breakInfo.breakAxes = breakAxes;
    breakInfo.annotationAxes = annotationAxes;
    breakInfo.invisibleObjects = invisibleObjects;
end

function list = RecursiveSetVisibleOff(handle) 
    list = [];
    list = SetVisibleOff(handle,list);
    
end 

function list = SetVisibleOff(handle, list)
    if (strcmp(get(handle,'Visible'),'on'))
        set(handle,'Visible','off');
        list = [list handle];
    end
    
    children = get(handle,'Children');
    for i = 1:numel(children)
        list = SetVisibleOff(children(i),list);
    end
end
    
function annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)

    %Create Annotation Axis, Remove graphics objects, XAxis annotations
    %(except XLabel) and make background transparent
    annotationAxes = copyobj(mainAxes,mainParent);
    
    set(annotationAxes,'YLimMode','Manual');
    
    children = get(annotationAxes,'Children');
    for i = 1:numel(children)
       delete(children(i)); 
    end

    %Save the xLabelpostion because it will move when we delete xAxis
    %ticks
    xLabel = get(annotationAxes,'XLabel');
    xLabelPosition = get(xLabel,'Position');
    
    set(annotationAxes,'XGrid' ,'off', ...
        'XMinorGrid', 'off', ...
        'XMinorTick','off', ...
        'XTick', [], ...
        'XTickLabel', []);
    
    %Restore the pevious label postition
    set(xLabel,'Position',xLabelPosition);
end

2.2 截断纵坐标

2.2.1 案例

MATLAB相关代码如下:

clear; 
clc; 
close all;
%% 纵轴截断后图像
% 数据
data=[2.3   2.1 1.9 1.8 1.7 1.7 1.7 1.7 1.7 1
3   2.5 2.1 2   1.9 1.9 1.9 1.9 1.9 1.2
3.4 3.3 3.2 3.1 3   3   3   3   3   2.5
10.8    10.6    10.5    10.2    10.1    10.1    10.1    10.1    10.1    9.1
];
%% 参数设置
x_min=0.1; %横坐标刻度最小值
x_interval=0.1; %横坐标刻度间隔距离
x_max=1; %横坐标刻度最大值
 
X=x_min:x_interval:x_max;
h=plot(X, data(1, :), 'k*-', X, data(2, :), 'g^-', X, data(3, :), 'r-s', X, data(4, :), 'b-x', 'MarkerFaceColor','y', 'MarkerSize',7,'linewidth',1.5);
 
set(gcf,'color','w')        %后面背景变白

xlim([x_min x_max]);    %横坐标范围
xlabel('X');
ylabel('Y');
hl = legend('Line-1', 'Line-2', 'Line-3', 'Line-4', 'Location', 'east');  %图例
set(hl,'Box','off','location','NorthOutside','NumColumns',4,'color','k');
% text( 'string',"(a) ", 'Units','normalized','position',[0.05,0.95],  'FontSize',14,'FontWeight','Bold','FontName','Times New Roman');   
set(gca,'Layer','top','FontSize',12,'Fontname', 'Times New Roman');
%% 调用已有的代码,两个函数只能调用一个,不能同时调用,出错
breakyaxis([4 9]);  % 截断纵坐标

saveas(gcf,sprintf('Other_Break_Axis.jpg'),'bmp'); %保存图片

图形如下:
【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)

2.2.2 调用函数

调用代码:

breakyaxis([minYvalue,maxYvalue])

函数代码:


% breakyaxes splits data in an axes so that data is in a low and high pane.
%
%   breakYAxes(splitYLim) splitYLim is a 2 element vector containing a range
%   of y values from splitYLim(1) to splitYLim(2) to remove from the axes.
%   They must be within the current yLimis of the axes.
%
%   breakYAxes(splitYLim,splitHeight) splitHeight is the distance to 
%   seperate the low and high side.  Units are the same as 
%   get(AX,'uints') default is 0.015
% 
%   breakYAxes(splitYLim,splitHeight,xOverhang) xOverhang stretches the 
%   axis split graphic to extend past the top and bottom of the plot by
%   the distance set by XOverhang.  Units are the same as get(AX,'units')
%   default value is 0.015
%
%   breakYAxes(AX, ...) performs the operation on the axis specified by AX
%
function breakInfo = breakyaxis(varargin)

    %Validate Arguements
    if nargin < 1 || nargin > 4
       error('Wrong number of arguements'); 
    end

    if isscalar(varargin{1}) && ishandle(varargin{1})
        mainAxes = varargin{1};
        argOffset = 1;
        argCnt = nargin - 1;
        if ~strcmp(get(mainAxes,'Type'),'axes')
           error('Handle object must be Type Axes'); 
        end
    else
        mainAxes = gca;
        argOffset = 0;
        argCnt = nargin;
    end
    
    if (strcmp(get(mainAxes,'XScale'),'log'))
        error('Log X Axes are not supported'); 
    end
    
    if (argCnt < 3)
        xOverhang = 0.015;
    else
        xOverhang = varargin{3 + argOffset};
        if  numel(xOverhang) ~= 1 || ~isreal(xOverhang) || ~isnumeric(xOverhang)
            error('XOverhang must be a scalar number');
        elseif (xOverhang < 0)
            error('XOverhang must not be negative');
        end
        xOverhang = double(xOverhang);
    end
    
    if (argCnt < 2)
        splitHeight = 0.015;
    else
        splitHeight = varargin{2 + argOffset};
        if  numel(xOverhang) ~= 1 || ~isreal(xOverhang) || ~isnumeric(xOverhang)
            error('splitHeight must be a scalar number');
        elseif (xOverhang < 0)
            error('splitHeight must not be negative');
        end
        splitHeight = double(splitHeight);
    end
    
    splitYLim = varargin{1 + argOffset};
    if numel(splitYLim) ~= 2 || ~isnumeric(splitYLim) || ~isreal(xOverhang)
       error(splitYLim,'Must be a vector length 2');
    end
    splitYLim = double(splitYLim);
    
    mainYLim = get(mainAxes,'YLim');
    if (any(splitYLim >= mainYLim(2)) || any(splitYLim <= mainYLim(1)))
       error('splitYLim must be in the range given by get(AX,''YLim'')');
    end
    
    mainPosition = get(mainAxes,'Position');
    if (splitHeight > mainPosition(3) ) 
       error('Split width is too large') 
    end
   
    %We need to create 4 axes
    % lowAxes - is used for the low y axis and low pane data
    % highAxes - is used to the high y axis and high pane data
    % annotationAxes - is used to display the x axis and title
    % breakAxes - this is an axes with the same size and position as main
    %   is it used to draw a seperator between the low and high side
    

    %Grab Some Parameters from the main axis (e.g the one we are spliting)
    mainYLim = get(mainAxes,'YLim');
    mainXLim = get(mainAxes,'XLim');
    mainPosition = get(mainAxes,'Position');
    mainParent = get(mainAxes,'Parent');
    mainHeight = mainPosition(4); %Positions have the format [low bottom width height]
    %mainYRange = mainYLim(2) - mainYLim(1);
    mainFigure = get(mainAxes,'Parent');
    mainXColor = get(mainAxes,'XColor');
    mainLineWidth = get(mainAxes,'LineWidth');
    figureColor = get(mainFigure,'Color');
    mainXTickLabelMode = get(mainAxes,'XTickLabelMode');
    mainYLabel = get(mainAxes,'YLabel');
    mainYDir = get(mainAxes,'YDir');
    mainLayer = get(mainAxes,'Layer');
    
    %Save Main Axis Z Order
    figureChildren = get(mainFigure,'Children');
    zOrder = find(figureChildren == mainAxes);
    
    %Calculate where axesLow and axesHigh will be layed on screen
    %And their respctive YLimits
    lowYLimTemp = [mainYLim(1) splitYLim(1)];
    highYLimTemp = [splitYLim(2) mainYLim(2)];

    lowYRangeTemp = lowYLimTemp(2) - lowYLimTemp(1);
    highYRangeTemp = highYLimTemp(2) - highYLimTemp(1);

    lowHeightTemp = lowYRangeTemp / (lowYRangeTemp + highYRangeTemp) * (mainHeight - splitHeight);
    highHeightTemp = highYRangeTemp / (lowYRangeTemp + highYRangeTemp) * (mainHeight - splitHeight);

    lowStretch = (lowHeightTemp + splitHeight/2) / lowHeightTemp;
    lowYRange = lowYRangeTemp * lowStretch;
    lowHeight = lowHeightTemp * lowStretch;

    highStretch = (highHeightTemp + splitHeight/2) / highHeightTemp;
    highYRange = highYRangeTemp * highStretch;
    highHeight = highHeightTemp * highStretch;
    
    lowYLim = [mainYLim(1) mainYLim(1)+lowYRange];
    highYLim = [mainYLim(2)-highYRange mainYLim(2)];
    
    if (strcmp(mainYDir, 'normal')) 
        lowPosition = mainPosition;
        lowPosition(4) = lowHeight; 

        highPosition = mainPosition;    %(!!!) look here for position indices!
        highPosition(2) = mainPosition(2) + lowHeight;
        highPosition(4) = highHeight;
    else
        %Low Axis will actually go on the high side a vise versa
        highPosition = mainPosition;
        highPosition(4) = highHeight; 

        lowPosition = mainPosition;
        lowPosition(2) = mainPosition(2) + highHeight;
        lowPosition(4) = lowHeight;
    end
 
    %Create the Annotations layer, if the Layer is top, draw the axes on
    %top (e.g. after) drawing the low and high pane
    if strcmp(mainLayer,'bottom')
        annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)
    end
    
    %Create and position the lowAxes. Remove all X Axis Annotations, the 
    %title, and a potentially offensive tick mark 
    lowAxes = copyobj(mainAxes,mainParent);
    set(lowAxes,'Position', lowPosition, ...
        'YLim', lowYLim, ... 
        'XLim', mainXLim, ...
        'XGrid' ,'off', ...
        'XMinorGrid', 'off', ...
        'XMinorTick','off', ...
        'XTick', [], ...
        'XTickLabel', [], ...
        'box','off');
    if strcmp(mainLayer,'bottom')
        set(lowAxes,'Color','none');
    end
    delete(get(lowAxes,'XLabel')); 
    delete(get(lowAxes,'YLabel'));
    delete(get(lowAxes,'Title'));
    
    if strcmp(mainXTickLabelMode,'auto')
        yTick =  get(lowAxes,'YTick');
        set(lowAxes,'YTick',yTick(1:(end-1)));
    end
    
    %Create and position the highAxes. Remove all X Axis annotations, the 
    %title, and a potentially offensive tick mark 
    highAxes = copyobj(mainAxes,mainParent);
    set(highAxes,'Position', highPosition, ...
        'YLim', highYLim, ...
        'XLim', mainXLim, ...
        'XGrid' ,'off', ...
        'XMinorGrid', 'off', ...
        'XMinorTick','off', ...
        'XTick', [], ...
        'XTickLabel', [], ...
        'box','off');
    if strcmp(mainLayer,'bottom') %(!!!) is it only about layers?
        set(highAxes,'Color','none');
    end
    delete(get(highAxes,'XLabel')); 
    delete(get(highAxes,'YLabel'));
    delete(get(highAxes,'Title'));
    
    if strcmp(mainXTickLabelMode,'auto')
        yTick =  get(highAxes,'YTick');
        set(highAxes,'YTick',yTick(2:end));
    end

        %Create the Annotations layer, if the Layer is top, draw the axes on
    %top (e.g. after) drawing the low and high pane
    if strcmp(mainLayer,'top')
        annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent);
        set(annotationAxes, 'Color','none');
    end
    
    %Create breakAxes, remove all graphics objects and hide all annotations
    breakAxes = copyobj(mainAxes,mainParent);
    children = get(breakAxes,'Children');
    for i = 1:numel(children)
       delete(children(i)); 
    end
    
    set(breakAxes,'Color','none');
    %Stretch the breakAxes horizontally to cover the vertical axes lines
    orignalUnits = get(breakAxes,'Units');
    set(breakAxes,'Units','Pixel');
    breakPosition = get(breakAxes,'Position');
    nudgeFactor = get(breakAxes,'LineWidth');
    breakPosition(3) = breakPosition(3) +  nudgeFactor;
    set(breakAxes,'Position',breakPosition);
    set(breakAxes,'Units',orignalUnits);

    %Stretch the breakAxes horizontally to create an overhang for sylistic
    %effect
    breakPosition = get(breakAxes,'Position');
    breakPosition(1) = breakPosition(1) - xOverhang;
    breakPosition(3) = breakPosition(3) +  2*xOverhang;
    set(breakAxes,'Position',breakPosition);
    
    %Create a sine shaped patch to seperate the 2 sides
    breakYLim = [mainPosition(2) mainPosition(2)+mainPosition(4)];
    set(breakAxes,'ylim',breakYLim);
    theta = linspace(0,2*pi,100);
    xPoints = linspace(mainXLim(1),mainXLim(2),100);
    amp = splitHeight/2 * 0.9;
    yPoints1 = amp * sin(theta) + mainPosition(2) + lowHeightTemp;
    yPoints2 = amp * sin(theta) + mainPosition(2) + mainPosition(4) - highHeightTemp;
    patchPointsY = [yPoints1 yPoints2(end:-1:1) yPoints1(1)];
    patchPointsX = [xPoints  xPoints(end:-1:1)  xPoints(1)];
    patch(patchPointsX,patchPointsY ,figureColor,'EdgeColor',figureColor,'Parent',breakAxes); %use of pathc(!!!)?

    %Create A Line To Delineate the low and high edge of the patch
    line('yData',yPoints1,'xdata',xPoints,'Parent',breakAxes,'Color',mainXColor,'LineWidth',mainLineWidth);
    line('yData',yPoints2,'xdata',xPoints,'Parent',breakAxes,'Color',mainXColor,'LineWidth',mainLineWidth);

    set(breakAxes,'Visible','off');
    
    %Make the old main axes invisiable
    invisibleObjects = RecursiveSetVisibleOff(mainAxes);

    %Preserve the z-order of the figure
    uistack([lowAxes highAxes breakAxes annotationAxes],'down',zOrder-1)
    
    %Set the rezise mode to position so that we can dynamically change the
    %size of the figure without screwing things up
    set([lowAxes highAxes breakAxes annotationAxes],'ActivePositionProperty','Position');
 
    %Playing with the titles labels etc can cause matlab to reposition
    %the axes in some cases.  Mannually force the position to be correct. 
    set([breakAxes annotationAxes],'Position',mainPosition);
    
    %Save the axes so we can unbreak the axis easily
    breakInfo = struct();
    breakInfo.lowAxes = lowAxes;
    breakInfo.highAxes = highAxes;
    breakInfo.breakAxes = breakAxes;
    breakInfo.annotationAxes = annotationAxes;
    breakInfo.invisibleObjects = invisibleObjects;
end

function list = RecursiveSetVisibleOff(handle) 
    list = [];
    list = SetVisibleOff(handle,list);
    
end 

function list = SetVisibleOff(handle, list)
    if (strcmp(get(handle,'Visible'),'on'))
        set(handle,'Visible','off');
        list = [list handle];
    end
    
    children = get(handle,'Children');
    for i = 1:numel(children)
        list = SetVisibleOff(children(i),list);
    end
end
    
function annotationAxes = CreateAnnotaionAxes(mainAxes,mainParent)

    %Create Annotation Axis, Remove graphics objects, YAxis annotations
    %(except YLabel) and make background transparent
    annotationAxes = copyobj(mainAxes,mainParent);
    
    set(annotationAxes,'XLimMode','Manual');
    
    children = get(annotationAxes,'Children');
    for i = 1:numel(children)
       delete(children(i)); 
    end

    %Save the yLabelpostion because it will move when we delete yAxis
    %ticks
    yLabel = get(annotationAxes,'YLabel');
    yLabelPosition = get(yLabel,'Position');
    
    set(annotationAxes,'YGrid' ,'off', ...
        'YMinorGrid', 'off', ...
        'YMinorTick','off', ...
        'YTick', [], ...
        'YTickLabel', []);
    
    %Restore the pevious label postition
    set(yLabel,'Position',yLabelPosition);
end

参考

1.博客-MATLAB实例:截断坐标轴(Broken Axis)文章来源地址https://www.toymoban.com/news/detail-460257.html

到了这里,关于【MATLAB基础绘图第9棒】绘制截断坐标轴(Broken Axis)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • R语言绘图-5-条形图(修改坐标轴以及图例等)

    1. 绘制条形图; 2. 添加文本并调整位置; 3. 调整x轴刻度的字体、角度及颜色; 4. 在导出pdf时,如果没有字体,该怎么解决问题;

    2024年02月08日
    浏览(43)
  • MATLAB: 调整坐标轴范围

    MATLAB: 调整坐标轴范围 在MATLAB中,可以使用一些方法来设置坐标轴的范围。通过调整坐标轴范围,可以改变绘图的可视化效果,并突出显示感兴趣的数据。本文将介绍一些常用的方法和示例代码。 使用axis函数设置坐标轴范围 axis函数是MATLAB中常用的设置坐标轴的函数之一。它

    2024年02月06日
    浏览(44)
  • matlab设置坐标轴的坐标显示范围和刻度

    所用代码: 逐个演示代码结果:   参考资料: matlab设置x轴和y轴的坐标显示范围和刻度_matalb的极坐标图如何将坐标标出来_phymat.nico的博客-CSDN博客

    2024年02月09日
    浏览(72)
  • Matlab中如何调整坐标轴刻度

    Matlab中如何调整坐标轴刻度 在Matlab中,我们经常需要对绘图中的坐标轴刻度进行调整,以便更好地展示数据。本文将介绍如何使用Matlab来调整坐标轴刻度,并提供相应的源代码示例供参考。 Matlab提供了多种方法来调整坐标轴刻度。下面我们将介绍其中的两种常用方法:手动

    2024年02月05日
    浏览(66)
  • Matlab隐藏坐标轴/数字/刻度线

    目录 一、隐藏坐标轴的数字 二、隐藏坐标轴的刻度 三、隐藏坐标轴 四、隐藏坐标区 五、修改坐标区背景颜色  六、修改图片背景颜色 一、隐藏坐标轴的数字 以X轴为例,在画图的代码后面增加以下设置: 二、隐藏坐标轴的刻度 三、隐藏坐标轴 四、隐藏坐标区 或者   五、

    2024年01月24日
    浏览(48)
  • 如何使Matlab输出图像坐标轴居中

    PS:写在前端,好久没有用CSDN了,现在公司入职,重新拾起社区文化,发扬总结和共享精神。 这个小点源于一位做深度学习的朋友,输出深度学习代表性函数的函数图像,由此找我帮忙找到解决方案。 首先,给出目标图像。 在这里,MATLAB一般是输出的结果为框线结果显示,

    2024年02月16日
    浏览(46)
  • Python数据可视化化第五节(子图的绘制及坐标轴共享)

    matplotlib可以将整个画布规划成等分布局的m n(行 列)的矩阵区域,并按照先行后列的·方式对每个区域进行编号(编号从1开始),之后在选中的某个区域或某些区域中绘制单个‘或多个子图。 使用pyplot的subplot()函数可以规划好的某个区域中绘制单个子图,subplot()函数的语法格

    2024年02月02日
    浏览(42)
  • python绘制子图技巧——plt.subplot和plt.subplots、及坐标轴修改

    偶然发现 python(matplotlib) 中绘制子图有两种方法,一种是 plt.subplot ,另一种是 plt.subplots ,这篇博客说一下这两种方法的区别,用法,以及常用的一些函数。 plt.figure 的作用是定义一个大的图纸,可以设置图纸的大小、分辨率等,例如 plt.plot() 是直接在当前活跃的的axes上面

    2023年04月09日
    浏览(40)
  • MATLAB 之 图形对象及其句柄和图形窗口与坐标轴

    MATLAB 的图形系统是面向图形对象的。图形对象是 MATLAB 图形元素的集合,是用于显示图形和设计用户界面的基本要素。 在 MATLAB 中,每一个具体的图形都是若干个不同的图形对象组成的。所有的图形对象都按父对象和子对象的方式组成层次结构,其形式如下图所示。 在图形对

    2024年02月09日
    浏览(48)
  • Matlab图坐标轴数值负号改为减号(change the hyphen (-) into minus sign (−, “U+2212”))

    在MATLAB中,坐标轴负数默认符号是 - ,如下图所示 可通过以下两语句将负号修改为减号: 或者 示例: 参考链接:change the hyphen (-) into minus sign (−, “U+2212”)

    2024年02月12日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包