# Question about aligning x-axes in subplots on the same row in Matlab

12 views (last 30 days)
Hung Dao on 24 Apr 2023
Commented: Dyuman Joshi on 4 May 2023
Dear Matlab experts,
I have a question about creating a plot consisting of 4 subplots arranged in a 2 by 2 grid. I want to align the x-axes of the subplots that are on the same row, while preserving their individual y-limits. I do not want to change the size of any subplot. To provide a visual reference, I have attached a sketch of the plot that I want to produce (Please forgive me for the ugly draw!)
Edit: Thank you for your prompt response, Matlab experts. Your proposed solutions have been effective for this simple case. However, I am having difficulty implementing your suggestions to solve my particular problem. I acknowledge that this is due to my own oversight, as I oversimplified my question. I apologize for any inconvenience this may have caused.
To elaborate further, each subplot in my code contains more than one function and includes vertical error bars as well. To facilitate your understanding, I have included my Matlab code below for your reference. The plot below is created from the given code. As you can see, the x-axises are not yet aligned and the ylim are different across subplots. I would like to have the x-axises aligned (for subplot on the same row) but keep the ylim of individual subplot unchanged. Thank you very much!
rng(12345)
% ----------- generate fake data --------------
% mu = [-1 0 5 -2 1 4 -6 0];
mu = randn(1,8);
MU = [mu,mu*rand(),10*mu*rand(), 100*mu*rand(),...
-mu,mu*rand(),-0.1*mu*rand(), -10*mu*rand()];
vars = [1 0.1 32 4 0.5 10 16 1];
COVMAT = diag([vars,vars*rand(),10*vars*rand(), 100*vars*rand(),...
vars,vars*rand(),10*vars*rand(), 100*vars*rand()]);
sim_data = mvnrnd(MU,COVMAT,100)';
% ----------- config error bars -------------
error_bar_tail_size = 10;
error_bar_size = 2;
% ----------- plotting -------------
fig_count = 9;
fig_num = 1;
for i = 1:8
if fig_count >8
figure(fig_num);
fig_num = fig_num + 1;
fig_count = 1;
end
subplot(2,4,fig_count)
fig_count = fig_count + 1;
idx = ((i-1)*8 + 1):(i*8);
hold on
x = 1:1:4;
percentiles = prctile(sim_data(idx(1:4),:),[2.5 50 97.5],2);
y1 = percentiles(:,2);
yneg1 = abs(y1 - percentiles(:,1));
ypos1 = abs(y1 - percentiles(:,3));
percentiles = prctile(sim_data(idx(5:8),:),[2.5 50 97.5],2);
y2 = percentiles(:,2);
yneg2 = abs(y2 - percentiles(:,1));
ypos2 = abs(y2 - percentiles(:,3));
% plot first error bars
e1 = errorbar(x-0.15,y1,yneg1,ypos1,'.','MarkerSize',27,'CapSize',error_bar_tail_size);
e1.LineWidth = error_bar_size;
% plot second error bars
e2 = errorbar(x+0.15,y2,yneg2,ypos2,'.','MarkerSize',27,'CapSize',error_bar_tail_size);
e2.LineWidth = error_bar_size;
% set axis limits and labels
xlim([0.5 4.5])
yline(0,'LineWidth',1)
xaxisproperties= get(gca, 'XAxis');
xaxisproperties.TickLabelInterpreter = 'latex';
xticks(x)
ax = gca;
ax.FontSize = 18;
title(['subplot ',num2str(i)],'FontSize',22,'Interpreter','latex')
hold off
end

Dyuman Joshi on 24 Apr 2023
One way to achieve this is to modify y-limits.
figure
x = linspace(0,10,1e3);
subplot(2,2,1)
y1 = sin(x);
plot(x,y1)
yline(0)
ylim(max(abs(ylim)).*[-1 1])
subplot(2,2,2)
y2 = exp(x);
plot(x,y2)
yline(0)
ylim(max(abs(ylim)).*[-1 1])
subplot(2,2,3)
y3 = -exp(sin(x));
plot(x,y3)
yline(0)
ylim(max(abs(ylim)).*[-1 1])
subplot(2,2,4)
y4 = 10*x.^(1/2);
plot(x,y4)
yline(0)
ylim(max(abs(ylim)).*[-1 1])
Though I feel it would be nice to have an option like
axis center
%or
axis origin
Hung Dao on 24 Apr 2023
Thank you very much for your prompt response! However, my problem is more complicated and I have edited my question.
Dyuman Joshi on 4 May 2023
Apologies for late reply. You can use the above approach here as well
rng(12345)
% ----------- generate fake data --------------
% mu = [-1 0 5 -2 1 4 -6 0];
mu = randn(1,8);
MU = [mu,mu*rand(),10*mu*rand(), 100*mu*rand(),...
-mu,mu*rand(),-0.1*mu*rand(), -10*mu*rand()];
vars = [1 0.1 32 4 0.5 10 16 1];
COVMAT = diag([vars,vars*rand(),10*vars*rand(), 100*vars*rand(),...
vars,vars*rand(),10*vars*rand(), 100*vars*rand()]);
sim_data = mvnrnd(MU,COVMAT,100)';
% ----------- config error bars -------------
error_bar_tail_size = 10;
error_bar_size = 2;
% ----------- plotting -------------
fig_count = 9;
fig_num = 1;
for i = 1:8
if fig_count >8
figure(fig_num);
fig_num = fig_num + 1;
fig_count = 1;
end
subplot(2,4,fig_count)
fig_count = fig_count + 1;
idx = ((i-1)*8 + 1):(i*8);
hold on
x = 1:1:4;
percentiles = prctile(sim_data(idx(1:4),:),[2.5 50 97.5],2);
y1 = percentiles(:,2);
yneg1 = abs(y1 - percentiles(:,1));
ypos1 = abs(y1 - percentiles(:,3));
percentiles = prctile(sim_data(idx(5:8),:),[2.5 50 97.5],2);
y2 = percentiles(:,2);
yneg2 = abs(y2 - percentiles(:,1));
ypos2 = abs(y2 - percentiles(:,3));
% plot first error bars
e1 = errorbar(x-0.15,y1,yneg1,ypos1);
e1.LineWidth = error_bar_size;
% plot second error bars
e2 = errorbar(x+0.15,y2,yneg2,ypos2);
e2.LineWidth = error_bar_size;
% set axis limits and labels
xlim([0.5 4.5])
%%define ylimits manually to be symmetrical across x-axis
ylim(max(abs(ylim)).*[-1 1])
yline(0,'LineWidth',1)
xaxisproperties= get(gca, 'XAxis');
xaxisproperties.TickLabelInterpreter = 'latex';
xticks(x)
title(['subplot ',num2str(i)],'Interpreter','latex')
hold off
end

Nithin Kumar on 24 Apr 2023
Edited: Nithin Kumar on 24 Apr 2023
Hi Hung,
I understand that you are trying to create a plot consisting of 4 subplots arranged in a 2 by 2 grid and align the x-axes of the subplots on the same row, while preserving their Individual y-limits (Even though the Y- axes values are different, the subplot needs to look like the same for a visual reference).
Kindly refer the following code below to create the required plot.
% Generating example data
x1 = linspace(0, 10, 100);
y1 = sin(x1);
x2 = linspace(0, 10, 50);
y2 = cos(x2);
x3 = linspace(0, 10, 200);
y3 = exp(x3);
x4 = linspace(0, 10, 75);
y4 = tan(x4);
% Creating the figure and subplots
figure
subplot(2, 2, 1)
plot(x1, y1)
title('Subplot 1')
set(gca,'FontSize',12)
subplot(2, 2, 2)
plot(x2, y2)
title('Subplot 2')
set(gca,'FontSize',12)
subplot(2, 2, 3)
plot(x3, y3)
title('Subplot 3')
ylabel('y-axis label')
set(gca,'FontSize',12)
subplot(2, 2, 4)
plot(x4, y4)
title('Subplot 4')
set(gca,'FontSize',12)
% Adjusting the x-axis limits and tick marks
xlim([0 10])
set(gca, 'XTick', [0:2:10])
% Adjusting the y-axis limits for each subplot
ylim(gca, [min([y1 y2 y3 y4]) max([y1 y2 y3 y4])])
% Adjusting the size of each subplot to be the same
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0 0 1 1])
Dyuman Joshi on 24 Apr 2023
Nithin, the bottom subplots don't seem to be correct.
Hung Dao on 24 Apr 2023
Thank you for your response! However, I have editted my question as it seems that the problem I am facing is a bit more complicated.