Decreasing gaps between subplots

8 vues (au cours des 30 derniers jours)
Aaro
Aaro le 1 Avr 2025
Modifié(e) : dpb le 4 Avr 2025
Hi,
How can I decrease the distances between subplots? For instance, let's say I have the following simple code, which produces four subplots:
figure(1)
clf
x = [1 2 3 4 5 6 7 8 9 10];
y = [1 4 9 16 25 36 49 64 81 100];
subplot(2,2,1)
plot(x,y)
grid on
xticklabels("")
subplot(2,2,2)
plot(x,y)
grid on
xticklabels("")
yticklabels("")
subplot(2,2,3)
plot(x,y)
grid on
subplot(2,2,4)
plot(x,y)
grid on
yticklabels("")
There are big gaps between the subplots. How can I change the code so that the gaps are smaller? Preferrably so that there are really small gaps, or no gaps at all.
  3 commentaires
dpb
dpb le 1 Avr 2025
Modifié(e) : dpb le 1 Avr 2025
I knew this was coming...but it's such a nuisance I didn't put it into the previous code.
You have to adjust the position property proportionally for all of them, keeping the top and bottom of the first and last rows, respectively, at the same locations. Similarly for the width; the left and rightmost positions have to stay in the same locations.
R=5; C=4;
n=0;
for r=1:R
for c=1:C
n=n+1;
hAx(r,c)=subplot(R,C,n);
plot(randn(10,1)) % plot into axis here (or can wait and use handle form)
end
end
set(hAx(1:end-1,:),{'xticklabel'},{''}) % clear tick labels except first column, last row
set(hAx(:,2:end),{'yticklabel'},{''}) % clear tick labels except first column, last row
set(hAx,{'xgrid','ygrid','box'},{'on','on','on'}) % turn on grids and box
set([hAx.XAxis;hAx.YAxis],{'TickLabelFormat'},{'%0.1f'}) % set consistent formatting
set(hAx,{'Ylim','Xlim'},{[-3 3],[0 10]}) % set uniform axis limits
POS=reshape([hAx(:,1).Position],4,[]).' % the position 4-vector for each row, first column
POS = 5×4
0.1300 0.8007 0.1566 0.1243 0.1300 0.6280 0.1566 0.1243 0.1300 0.4553 0.1566 0.1243 0.1300 0.2827 0.1566 0.1243 0.1300 0.1100 0.1566 0.1243
<mw-icon class=""></mw-icon>
<mw-icon class=""></mw-icon>
TOP=POS(1,2)+POS(1,4) % the very topmost position --> bottom of top row plus its height
TOP = 0.9250
BOT=POS(end,2) % bottom position
BOT = 0.1100
h=(TOP-BOT)/R % height of each to have zero clearance
h = 0.1630
hAdj=h/POS(1,4) % the height adjustment factor/ratio
hAdj = 1.3111
What have to do is take the overall TOP/BOT numbers and split them up to make the bottom of the next row the top of the row below, then do the similar exercise for the left and width values.
I'm not up to messing with it now, but that's the outline.
ADDENDUM
"...so that there are really small gaps, or no gaps at all."
Nota Bene: If you eliminate the gaps entirely, then the tick labels you have chosen to show will end up overlapping as well.
dpb
dpb le 1 Avr 2025
@Stephen23 "...that tiledlayout supports this option:..."
I will agree new code really ought to use the tiledlayout, but even the 'compact' option has quite a lot of whitepace remaining that can't eliminate.

Connectez-vous pour commenter.

Réponses (2)

Umar
Umar le 2 Avr 2025

Hi @Aaro,

To decrease the distances between subplots in MATLAB, you can utilize the `Position` property of each subplot or use the `tight_subplot` function if you prefer a more automated approach. Below, I’ll demonstrate both methods.

Method 1: Adjusting Subplot Positions Manually

You can manually set the position of each subplot using the `subplot` function and adjusting the `Position` property. Here’s how you can modify your code:

figure(1)
clf
x = [1 2 3 4 5 6 7 8 9 10];
y = [1 4 9 16 25 36 49 64 81 100];
% Define positions for each subplot
subplot(2,2,1)
plot(x,y)
grid on
xticklabels("")
set(gca, 'Position', [0.1, 0.55, 0.35, 0.35]) % Adjusted position
subplot(2,2,2)
plot(x,y)
grid on
xticklabels("")
yticklabels("")
set(gca, 'Position', [0.55, 0.55, 0.35, 0.35]) % Adjusted position
subplot(2,2,3)
plot(x,y)
grid on
set(gca, 'Position', [0.1, 0.1, 0.35, 0.35]) % Adjusted position
subplot(2,2,4)
plot(x,y)
grid on
yticklabels("")
set(gca, 'Position', [0.55, 0.1, 0.35, 0.35]) % Adjusted position

In this example: - The `set(gca, 'Position', ...)` command allows you to specify the `[left bottom width height]` of each subplot. - By tweaking these values (e.g., decreasing `left`, `bottom`, and increasing `width`, `height`), you can effectively reduce the space between subplots.

Method 2: Using `tight_subplot`

If you want an automated solution that handles spacing more elegantly without needing to adjust each subplot individually, consider using the `tight_subplot` function from MATLAB File Exchange or similar resources.Here’s an example of how to use it

% If you don't have tight_subplot installed, download it from MATLAB File Exchange   first.
figure(1)
clf
x = [1 2 3 4 5 6 7 8 9 10];
y = [1 4 9 16 25 36 49 64 81 100];
% Create a tight subplot with no gaps
ha = tight_subplot(2,2,[0.01 .01],[0.05 .05],[0.05 .05]);
axes(ha(1)); plot(x,y); grid on; xticklabels("");
axes(ha(2)); plot(x,y); grid on; xticklabels(""); yticklabels("");
axes(ha(3)); plot(x,y); grid on;
axes(ha(4)); plot(x,y); grid on; yticklabels("");

In this example: - The `tight_subplot` function allows you to specify vertical and horizontal gaps as well as margins. - Setting these parameters to small values (e.g., `[0.01 .01]` for gaps and `[0.05 .05]` for margins) will significantly reduce or eliminate spacing between subplots.

Considerations: When adjusting subplot spacing too tightly, ensure that axis labels and titles remain legible and do not overlap with neighboring plots.

Visual Appeal: Aesthetics matter in data visualization; while reducing gaps can create a compact look, it's essential to maintain clarity in presenting your data.

By applying one of these methods, you should be able to achieve the desired effect of minimal or no gaps between your subplots in MATLAB effectively!

  1 commentaire
Aaro
Aaro le 2 Avr 2025
Thank you! The 'tight_subplot' function works otherwise, but then the values on the x- and y-axis overlap. The method 1 seems to be the best, but it just takes a long time to manually adjust all the subplots.

Connectez-vous pour commenter.


dpb
dpb le 2 Avr 2025
Modifié(e) : dpb le 3 Avr 2025
OK, I had some time to work out a method that is pretty simple...on further inspection, one can let the panes remain in their original position and just adjust the height and width -- up to some limit, of course -- and have them stay inside the figure boundary.
The follwing function will allow one to set a fraction of the free space between the default pane axes inside the individual panes; the example is run for a 50% reduction of the default vertical space/margin but only 40% for horizontal..the x-axis labels overlap if use 50% in both directions. Even here, the RH "10" looks like "100" because there isn't enough white space left to distinguish the two from each other. I don't know that can do much better unless move the tick labels.
This function is far from being production-level code; while it works well for what it is intended to do, its action is non-reversible and can only be applied once to an existing set of subplots; the full set of axes/plots needs to be recreated to make an adjustment in the values chosen; however, it is possible to create the set of axes in the desired configuration and then add the plotting data into them later if generating the plot data is time-consuming. Adding the rollback feature, etc., is left as "exercise for Student"... :J>
R=5; C=4;
n=0;
for r=1:R
for c=1:C
n=n+1;
hAx(r,c)=subplot(R,C,n);
plot(randn(10,1)) % plot into axis here (or can wait and use handle form)
end
end
set(hAx(1:end-1,:),{'xticklabel'},{''}) % clear tick labels except first column, last row
set(hAx(:,2:end),{'yticklabel'},{''}) % clear tick labels except first column, last row
set(hAx,{'xgrid','ygrid','box'},{'on','on','on'}) % turn on grids and box
set([hAx.YAxis],{'TickLabelFormat'},{'%0.1f'}) % set consistent formatting
set(hAx,{'Ylim','Xlim'},{[-3 3],[0 10]}) % set uniform axis limits
VGAP=0.5;
HGAP=0.4;
adjustGap(hAx,VGAP,HGAP)
function adjustGap(hAx,VGAP,HGAP)
% adjust set of suplot axes to leave GAP percentage between axes
% presumes an array of subplot axes handles; this function is only applied after a mapping is complete
[R,C]=size(hAx); % number rows, columns
POSN=reshape([hAx.Position],4,[]).'; % get the whole enchilada to adjust
H0=POSN(1,end); % bottom origin position for vertical adjustment
H_PANEL=abs(diff(POSN(1:2,2))); % overall vertical height of each pane
H_FREE=H_PANEL-H0; % free vertical distance from bottom to next vertical pane
W0=POSN(1,1); % left origin
W_PANEL=POSN(R+1,1)-POSN(1,1); % overall panel width
W_FREE=W_PANEL-W0; % free width of panes
POS=POSN; % adjusted positions array
POS(:,3)=POS(:,3)+W_FREE*HGAP;
POS(:,4)=POS(:,4)+H_FREE*VGAP;
n=0;
for j=1:C
for i=1:R
n=n+1;
hAx(i,j).Position=POS(n,:);
end
end
end
  3 commentaires
Image Analyst
Image Analyst le 3 Avr 2025
Can you show both the big space version and the small space version so we can compare the two?
dpb
dpb le 3 Avr 2025
Modifié(e) : dpb le 4 Avr 2025
Sure...
R=5; C=4;
hAx=buildFigure(R,C);
hAx=buildFigure(R,C); VGAP=0.5; HGAP=0.35; adjustGap(hAx,VGAP,HGAP)
function hAx=buildFigure(R,C)
figure
n=0;
for r=1:R
for c=1:C
n=n+1;
hAx(r,c)=subplot(R,C,n);
plot(randn(10,1)) % plot into axis here (or can wait and use handle form)
end
end
set(hAx(1:end-1,:),{'xticklabel'},{''}) % clear tick labels except first column, last row
set(hAx(:,2:end),{'yticklabel'},{''}) % clear tick labels except first column, last row
set(hAx,{'xgrid','ygrid','box'},{'on','on','on'}) % turn on grids and box
set([hAx.YAxis],{'TickLabelFormat'},{'%0.1f'}) % set consistent formatting
set(hAx,{'Ylim','Xlim'},{[-3 3],[0 10]}) % set uniform axis limits
end
function adjustGap(hAx,VGAP,HGAP)
% adjust set of suplot axes to leave GAP percentage between axes
% presumes an array of subplot axes handles; this function is only applied after a mapping is complete
[R,C]=size(hAx); % number rows, columns
POSN=reshape([hAx.Position],4,[]).'; % get the whole enchilada to adjust
H0=POSN(1,end); % bottom origin position for vertical adjustment
H_PANEL=abs(diff(POSN(1:2,2))); % overall vertical height of each pane
H_FREE=H_PANEL-H0; % free vertical distance from bottom to next vertical pane
W0=POSN(1,1); % left origin
W_PANEL=POSN(R+1,1)-POSN(1,1); % overall panel width
W_FREE=W_PANEL-W0; % free width of panes
POS=POSN; % adjusted positions array
POS(:,3)=POS(:,3)+W_FREE*HGAP;
POS(:,4)=POS(:,4)+H_FREE*VGAP;
n=0;
for j=1:C
for i=1:R
n=n+1;
hAx(i,j).Position=POS(n,:);
end
end
end
I also shrunk the XGAP just a little more to give some space between adjacent xticklabels.

Connectez-vous pour commenter.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by