在 MATLAB 中将坐标轴与绘图区域分开
Separating axes from plot area in MATLAB
我发现位于轴上或轴附近的数据点很难看清。当然,最明显的解决方法是使用 axis([xmin xmax ymin ymax])
简单地更改绘图区域,但这并不是在所有情况下都可取;例如,如果 x 轴是时间,则将最小 x 值移动到 -1 以显示 activity 为 0 是没有意义的。
相反,我希望简单地将 x 轴和 y 轴从绘图区域移开,就像我在这里所做的那样:
左:MATLAB 生成,右:所需(图像编辑软件)
有没有办法在 MATLAB 中自动执行此操作?我认为可能有一种方法可以通过使用 outerposition
轴 属性(即将其设置为 [0 0 0.9 0.9]
并在原来的位置绘制新轴?),但我没有使用该策略不会有任何结果。
您可以从小于零的位置开始轴,然后从绘图中删除小于零的刻度。例如
plot(0:3:30,0:3:30); %Some random data for plotting
h = gca;
axis([-1 30 -1 30]); %Setting the axis from less than zero
box off; %Removing box
h.TickDir = 'out'; %Setting Direction of ticks to outwards
h.XTickLabel(1)= {' '}; %Removing the first tick of X-axis
h.YTickLabel(1)= {' '}; %Removing the first tick of Y-axis
使用此代码,您将得到以下结果:
这可能有一个缺点,有时,零刻度也可能会被删除(如上图所示)。这是因为该图已将轴的第一个刻度设置为零。使用 if
条件可以避免这种情况。所以,代码可以修改如下:
plot(0:3:30,0:3:30);
h = gca;
axis([-1 30 -1 30]);
box off;
h.TickDir = 'out';
if str2num(cell2mat(h.XTickLabel(1))) <0
h.XTickLabel(1)= {' '};
end
if str2num(cell2mat(h.YTickLabel(1))) <0
h.YTickLabel(1)= {' '};
end
以上代码将产生以下结果:-
另请注意,对于您的情况,由于您的轴刻度非常小,-1
可能不太适合轴的起始值,您可能需要使用 -0.1
代替,即axis([-0.1 30 -0.1 30]);
这里有一个简单的实现方法:
% some data:
x = 1:100;
f=@(x) 5.*x;
y=f(x)+rand(1,length(x))*50;
close all
% plotting:
f1 = figure('Color','white');
ax = axes;
plot(ax,x,y,'o');
% 'clean' the data area a little bit:
box off
ax.TickDir = 'out';
% pushing the axis a bit forward:
lims = axis;
pos = ax.Position;
axis([lims(1)-ax.XTick(2)/5 lims(2)+0.1 lims(3)-ax.YTick(2)/5 lims(4)+0.1])
% Create lines
firstXtick = 0.013; %this value need to be adjusted only once per figure
firstYtick = 0.023; %this value need to be adjusted only once per figure
lx = annotation(f1,'line',[pos(1) pos(1)+firstXtick],...
[pos(2) pos(2)],'Color',[1 1 1],'LineWidth',1);
ly = annotation(f1,'line',[pos(1) pos(1)],...
[pos(2) pos(2)+firstYtick],'Color',[1 1 1],'LineWidth',1);
产生这个数字:
这里唯一要调整的是 firstXtick
和 firstYtick
值,必须针对特定轴进行微调,每种类型的图形一次。将它们设置为正确的值后,可以毫无问题地调整图形的大小。缩放和平移需要一些修复。
此处的答案已经向您展示了大部分内容 - 这是根据您放在一起的示例分离 x 轴和 y 轴的最后一步。
f = figure ( 'color', 'white' );
% create the axes and set some properties
ax = axes ( 'parent', f, 'box', 'off', 'nextplot', 'add', 'XMinorTick', 'on', 'YMinorTick', 'on' );
% plot some data
plot ( ax, 0:10, [0:10].^2, 'rx-' )
% modify the x and y limits to below the data (by a small amount)
ax.XLim(1) = ax.XLim(1)-(ax.XTick(2)-ax.XTick(1))/4;
ax.YLim(1) = ax.YLim(1)-(ax.YTick(2)-ax.YTick(1))/4;
% Set the tick direction
ax.TickDir = 'out';
% draw the plot to generate the undocumented vertex data var
drawnow()
%% R2015a
% X, Y and Z row of the start and end of the individual axle.
ax.XRuler.Axle.VertexData(1,1) = 0;
ax.YRuler.Axle.VertexData(2,1) = 0;
%% R2015b
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
vd = get(ax.XAxis.Axle,'VertexData');
% reset the zero value
vd(1,1) = 0;
% Update the vertex data
set(ax.XAxis.Axle,'VertexData',vd);
% repeat for Y (set 2nd row)
vd = get(ax.YAxis.Axle,'VertexData');
vd(2,1) = 0;
set(ax.YAxis.Axle,'VertexData',vd);
编辑: 顶点是 Matlab 在 axes/figure 改变大小或缩放或平移时重新创建的东西。
您可以尝试通过添加侦听器来尝试捕获此问题(请记住,您在此处使用的是未记录的功能)来抵消此问题。我们可以使用被调用很多次的 MarkedClean
事件。
addlistener ( ax, 'MarkedClean', @(obj,event)resetVertex(ax) );
resetVertex 函数类似于:(仅显示 R2015b)
编辑 2 添加了关闭低于 0 的小刻度的代码。
function resetVertex ( ax )
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
ax.XAxis.Axle.VertexData(1,1) = 0;
% repeat for Y (set 2nd row)
ax.YAxis.Axle.VertexData(2,1) = 0;
% You can modify the minor Tick values by modifying the vertex data
% for them, e.g. remove any minor ticks below 0
ax.XAxis.MinorTickChild.VertexData(:,ax.XAxis.MinorTickChild.VertexData(1,:)<0) = [];
ax.YAxis.MinorTickChild.VertexData(:,ax.YAxis.MinorTickChild.VertexData(2,:)<0) = [];
end
注意:这使用了未记录的功能 -> 因此可能仅适用于某些版本的 Matlab(我已经添加了 r2015a 和 r2015b 的代码)并且 Matlab 可能会根据您对绘图所做的操作重新创建顶点数据。
通过对@matlabgui 的回答稍作修改,您可以跟踪(主要)滴答限制:
ax = gca();
% Set the tick direction
ax.TickDir = 'out';
% Make sure this stays when saving, zooming, etc
addlistener ( ax, 'MarkedClean', @(obj,event) change_ticks(ax) );
% Draw the plot to generate the undocumented vertex data variable
% and call callback for the first time
drawnow();
回调
function change_ticks( ax )
% Modify ruler
ax.XRuler.Axle.VertexData(1,1) = ax.XTick(1);
ax.XRuler.Axle.VertexData(1,2) = ax.XTick(end);
ax.YRuler.Axle.VertexData(2,1) = ax.YTick(1);
ax.YRuler.Axle.VertexData(2,2) = ax.YTick(end);
end
我没有广泛测试,但似乎也适用于自定义刻度。这不仅在零上而且在拳头和最后一个滴答声之外很好地切割了标尺。这在 Windows 上的 Matlab 2019a 中进行了测试,ax.XRuler.Axle.VertexData
工作正常。请注意,这仅适用于主要报价!
我发现位于轴上或轴附近的数据点很难看清。当然,最明显的解决方法是使用 axis([xmin xmax ymin ymax])
简单地更改绘图区域,但这并不是在所有情况下都可取;例如,如果 x 轴是时间,则将最小 x 值移动到 -1 以显示 activity 为 0 是没有意义的。
相反,我希望简单地将 x 轴和 y 轴从绘图区域移开,就像我在这里所做的那样:
有没有办法在 MATLAB 中自动执行此操作?我认为可能有一种方法可以通过使用 outerposition
轴 属性(即将其设置为 [0 0 0.9 0.9]
并在原来的位置绘制新轴?),但我没有使用该策略不会有任何结果。
您可以从小于零的位置开始轴,然后从绘图中删除小于零的刻度。例如
plot(0:3:30,0:3:30); %Some random data for plotting
h = gca;
axis([-1 30 -1 30]); %Setting the axis from less than zero
box off; %Removing box
h.TickDir = 'out'; %Setting Direction of ticks to outwards
h.XTickLabel(1)= {' '}; %Removing the first tick of X-axis
h.YTickLabel(1)= {' '}; %Removing the first tick of Y-axis
使用此代码,您将得到以下结果:
这可能有一个缺点,有时,零刻度也可能会被删除(如上图所示)。这是因为该图已将轴的第一个刻度设置为零。使用 if
条件可以避免这种情况。所以,代码可以修改如下:
plot(0:3:30,0:3:30);
h = gca;
axis([-1 30 -1 30]);
box off;
h.TickDir = 'out';
if str2num(cell2mat(h.XTickLabel(1))) <0
h.XTickLabel(1)= {' '};
end
if str2num(cell2mat(h.YTickLabel(1))) <0
h.YTickLabel(1)= {' '};
end
以上代码将产生以下结果:-
另请注意,对于您的情况,由于您的轴刻度非常小,-1
可能不太适合轴的起始值,您可能需要使用 -0.1
代替,即axis([-0.1 30 -0.1 30]);
这里有一个简单的实现方法:
% some data:
x = 1:100;
f=@(x) 5.*x;
y=f(x)+rand(1,length(x))*50;
close all
% plotting:
f1 = figure('Color','white');
ax = axes;
plot(ax,x,y,'o');
% 'clean' the data area a little bit:
box off
ax.TickDir = 'out';
% pushing the axis a bit forward:
lims = axis;
pos = ax.Position;
axis([lims(1)-ax.XTick(2)/5 lims(2)+0.1 lims(3)-ax.YTick(2)/5 lims(4)+0.1])
% Create lines
firstXtick = 0.013; %this value need to be adjusted only once per figure
firstYtick = 0.023; %this value need to be adjusted only once per figure
lx = annotation(f1,'line',[pos(1) pos(1)+firstXtick],...
[pos(2) pos(2)],'Color',[1 1 1],'LineWidth',1);
ly = annotation(f1,'line',[pos(1) pos(1)],...
[pos(2) pos(2)+firstYtick],'Color',[1 1 1],'LineWidth',1);
产生这个数字:
这里唯一要调整的是 firstXtick
和 firstYtick
值,必须针对特定轴进行微调,每种类型的图形一次。将它们设置为正确的值后,可以毫无问题地调整图形的大小。缩放和平移需要一些修复。
此处的答案已经向您展示了大部分内容 - 这是根据您放在一起的示例分离 x 轴和 y 轴的最后一步。
f = figure ( 'color', 'white' );
% create the axes and set some properties
ax = axes ( 'parent', f, 'box', 'off', 'nextplot', 'add', 'XMinorTick', 'on', 'YMinorTick', 'on' );
% plot some data
plot ( ax, 0:10, [0:10].^2, 'rx-' )
% modify the x and y limits to below the data (by a small amount)
ax.XLim(1) = ax.XLim(1)-(ax.XTick(2)-ax.XTick(1))/4;
ax.YLim(1) = ax.YLim(1)-(ax.YTick(2)-ax.YTick(1))/4;
% Set the tick direction
ax.TickDir = 'out';
% draw the plot to generate the undocumented vertex data var
drawnow()
%% R2015a
% X, Y and Z row of the start and end of the individual axle.
ax.XRuler.Axle.VertexData(1,1) = 0;
ax.YRuler.Axle.VertexData(2,1) = 0;
%% R2015b
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
vd = get(ax.XAxis.Axle,'VertexData');
% reset the zero value
vd(1,1) = 0;
% Update the vertex data
set(ax.XAxis.Axle,'VertexData',vd);
% repeat for Y (set 2nd row)
vd = get(ax.YAxis.Axle,'VertexData');
vd(2,1) = 0;
set(ax.YAxis.Axle,'VertexData',vd);
编辑: 顶点是 Matlab 在 axes/figure 改变大小或缩放或平移时重新创建的东西。
您可以尝试通过添加侦听器来尝试捕获此问题(请记住,您在此处使用的是未记录的功能)来抵消此问题。我们可以使用被调用很多次的 MarkedClean
事件。
addlistener ( ax, 'MarkedClean', @(obj,event)resetVertex(ax) );
resetVertex 函数类似于:(仅显示 R2015b)
编辑 2 添加了关闭低于 0 的小刻度的代码。
function resetVertex ( ax )
% extract the x axis vertext data
% X, Y and Z row of the start and end of the individual axle.
ax.XAxis.Axle.VertexData(1,1) = 0;
% repeat for Y (set 2nd row)
ax.YAxis.Axle.VertexData(2,1) = 0;
% You can modify the minor Tick values by modifying the vertex data
% for them, e.g. remove any minor ticks below 0
ax.XAxis.MinorTickChild.VertexData(:,ax.XAxis.MinorTickChild.VertexData(1,:)<0) = [];
ax.YAxis.MinorTickChild.VertexData(:,ax.YAxis.MinorTickChild.VertexData(2,:)<0) = [];
end
注意:这使用了未记录的功能 -> 因此可能仅适用于某些版本的 Matlab(我已经添加了 r2015a 和 r2015b 的代码)并且 Matlab 可能会根据您对绘图所做的操作重新创建顶点数据。
通过对@matlabgui 的回答稍作修改,您可以跟踪(主要)滴答限制:
ax = gca();
% Set the tick direction
ax.TickDir = 'out';
% Make sure this stays when saving, zooming, etc
addlistener ( ax, 'MarkedClean', @(obj,event) change_ticks(ax) );
% Draw the plot to generate the undocumented vertex data variable
% and call callback for the first time
drawnow();
回调
function change_ticks( ax )
% Modify ruler
ax.XRuler.Axle.VertexData(1,1) = ax.XTick(1);
ax.XRuler.Axle.VertexData(1,2) = ax.XTick(end);
ax.YRuler.Axle.VertexData(2,1) = ax.YTick(1);
ax.YRuler.Axle.VertexData(2,2) = ax.YTick(end);
end
我没有广泛测试,但似乎也适用于自定义刻度。这不仅在零上而且在拳头和最后一个滴答声之外很好地切割了标尺。这在 Windows 上的 Matlab 2019a 中进行了测试,ax.XRuler.Axle.VertexData
工作正常。请注意,这仅适用于主要报价!