You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Multiple X axis in different scale, but one y axis
115 views (last 30 days)
Show older comments
Hello,
How to Add Multiple X axis in different scale? Please help me? It will look like this:
Accepted Answer
Adam Danz
on 28 Jul 2020
Edited: Adam Danz
on 14 Apr 2022
Matlab does not support mutliple x axes other than the axes at the upper and lower borders of the plot.
One way to include multiple axis units is to create multi-lined x-axis ticks. The upper axis will be your main axis used to plot your data. Then define the axis limits for all additional pseudo-axes and compute the tick values for each pseudo-axis so they align with the x-ticks on the main axis. Use those value to create the multi-lined x-tick labels.
Follow the demo below and adjust it to fit your needs.
Demo
% Set up main axis (on top)
clf()
ax = axes();
ax.XTick = 0:200:2800;
ax.XLim = [0,2800];
% Set axis limits for all other axes
additionalAxisLimits = [...
0, 1400; % axis 2
19.2, 23.4; % axis 3
0.2, 3]; % axis 4
% Compute tick values for each axis to align with main axis
additionalAxisTicks = arrayfun(@(i){linspace(additionalAxisLimits(i,1), ...
additionalAxisLimits(i,2),numel(ax.XTick))}, 1:size(additionalAxisLimits,1));
% Set up multi-line ticks
allTicks = [ax.XTick; cell2mat(additionalAxisTicks')];
tickLabels = compose('%4d\\newline%4d\\newline%.1f\\newline%.1f', allTicks(:).');
% The %4d adds space to the left so the labels are centered.
% You'll need to add "%.1f\\newline" for each row of labels (change formatting as needed).
% Alternatively, you can use the flexible line below that works with any number
% of rows but uses the same formatting for all rows.
% tickLabels = compose(repmat('%.2f\\newline',1,size(allTicks,1)), allTicks(:).');
% Decrease axis height & width to make room for labels
ax.Position(3:4) = ax.Position(3:4) * .75; % Reduced to 75%
ax.Position(2) = ax.Position(2) + .2; % move up
% Add x tick labels
set(ax, 'XTickLabel', tickLabels, 'TickDir', 'out', 'XTickLabelRotation', 0)
% Define each row of labels
ax2 = axes('Position',[sum(ax.Position([1,3]))*1.08, ax.Position(2), .02, 0.001]);
linkprop([ax,ax2],{'TickDir','FontSize'});
axisLabels = {'Distance (t)','Area (m^2)','Cnt from 0 (m)','KB (m)'}; % one for each x-axis
set(ax2,'XTick',0.5,'XLim',[0,1],'XTickLabelRotation',0, 'XTickLabel', strjoin(axisLabels,'\\newline'))
ax2.TickLength(1) = 0.2; % adjust as needed to align ticks between the two axes
Similar examples in the forum
34 Comments
Alpha Boy
on 28 Jul 2020
% Set up main axis (on top)
ax = axes();
ax.XTick = 4000:5000:30000; %Disp
ax.XLim = [4000,30000];
% Set axis limits for all other axes
additionalAxisLimits = [...
3500, 4500; % axis 2 WPA
0,6; % axis 3 KB
20,30; % axis 4 LCB
30,50; %axis 5 TPC
200, 500; %axis 6 MCTC
0, 50; %axis 7 BMt
100,1500; %axis 8 BMl
20, 250; %axis 9 AM
0, 1; %axis 10 CB
0, 1; %axis 11 CM
0, 1; %axis 12 CP
0, 1; %axis 13 CWP
0, 1]; %axis 14 CVP
Output: :( Help me plz :( :(
Adam Danz
on 28 Jul 2020
Edited: Adam Danz
on 28 Jul 2020
I can't see what's wrong without seeing your code.
My guess is that you forgot this transpose,
tickLabels = compose('%4d\\newline%4d\\newline%.1f\\newline%.1f', allTicks(:).');
% ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ---> ^^
If that's not the problem go through your code line by line and compare the results to my version to see where it starts to differ.
Adam Danz
on 28 Jul 2020
I can't help without seeing your code. The code you provided in a comment above is incomplete.
Share the relevant section of code.
Alpha Boy
on 28 Jul 2020
% Set up main axis (on top)
ax = axes();
ax.XTick = 4000:5000:30000; %Disp
ax.XLim = [4000,30000];
% Set axis limits for all other axes
additionalAxisLimits = [...
3500, 4500; % axis 2 WPA
0,6; % axis 3 KB
20,30; % axis 4 LCB
30,50; %axis 5 TPC
200, 500; %axis 6 MCTC
0, 50; %axis 7 BMt
100,1500; %axis 8 BMl
20, 250; %axis 9 AM
0, 1; %axis 10 CB
0, 1; %axis 11 CM
0, 1; %axis 12 CP
0, 1; %axis 13 CWP
0, 1]; %axis 14 CVP
% Compute tick values for each axis to align with main axis
additionalAxisTicks = arrayfun(@(i){linspace(additionalAxisLimits(i,1), ...
additionalAxisLimits(i,2),numel(ax.XTick))}, 1:size(additionalAxisLimits,1));
% Set up multi-line ticks
allTicks = [ax.XTick; cell2mat(additionalAxisTicks')];
tickLabels = compose('%14d\\newline%14d\\newline%.1f\\newline%.1f', allTicks(:).');
% The %4d adds space to the left so the labels are centered.
% Decrease axis height & width to make room for labels
ax.Position(3:4) = ax.Position(3:4) * .75; % Reduced to 75%
ax.Position(2) = ax.Position(2) + .2; % move up
% Add x tick labels
set(ax, 'XTickLabel', tickLabels, 'TickDir', 'out')
% Define each row of labels
ax2 = axes('Position',[sum(ax.Position([1,3]))*1.1, ax.Position(2), .02, 0]);
linkprop([ax,ax2],{'TickDir','TickLength','FontSize'})
axisLabels = {'Distance (t)','Area (m^2)','Cnt from 0 (m)','KB (m)'}; % one for each x-axis
set(ax2,'XTick',0.5,'XLim',[0,1],'XTickLabel', strjoin(axisLabels,'\\newline'))
Here it is.
Adam Danz
on 28 Jul 2020
I see your mistake. You didn't expand the compose() function beyond the 4 rows I have in my demo. It's very important that you go through each line of code to understand what it does so you can learn something and so you can own your work and call it yours.
I've updated my answer to show how to flexibly create the compose() line no matter how many rows are in the tick labels. There are several small changes to my answer that you should look for but here's are the 3 main changes you need to make to your code.
1) replace the old compose() line with this one.
tickLabels = compose(repmat('%.2f\\newline',1,size(allTicks,1)), allTicks(:).');
Note that all of your labels will now have 2 dp.
2) Since you have so many rows of labels, you'll need to shrink the height of your axes even further.
% Decrease axis height & width to make room for labels
ax.Position(3) = ax.Position(3) * .75; % Reduced width to 75%
ax.Position(4) = ax.Position(4) * .40; % Reduced height to 40%
ax.Position(2) = ax.Position(2) + .48; % move up
3) Fill in the rest of the axis labels (see axisLabels variable).
Adam Danz
on 28 Jul 2020
By the way, if those axis limits are your real data, you could remove the last 4 rows since they are the same scale. That gives you more space for the plot.
Alpha Boy
on 28 Jul 2020
Wow, it works. And at the last moment one last question, How can I get the lines, I mean the graph.
Alpha Boy
on 28 Jul 2020
Where, I have to put, grid on?
I have tables, I have values of X and Y axis
How can I put those?
Adam Danz
on 28 Jul 2020
The grid command places the vertical and horiztonal grid lines on the axes.
To plot the data, use the plot command. The x-values should be in the same units as your main axes on top (ranging from 4000 to 30000).
If you have trouble plotting, you may want to go through the Matlab Onramp to learn the basics.
Alpha Boy
on 28 Jul 2020
I am a newbie in MATLab. I simply plot (x,y). But here, 14 different scale. So I cannot get it. Can you give me some idea for it? I would be greatfull.
Alpha Boy
on 28 Jul 2020
% Set up main axis (on top)
ax = axes();
ax.XTick = 4000:5000:30000; %Disp
ax.XLim = [4000,30000];
% Set axis limits for all other axes
additionalAxisLimits = [...
3500, 4500; % axis 2 WPA
0,6; % axis 3 KB
20,30; % axis 4 LCB
30,50; %axis 5 TPC
200, 500; %axis 6 MCTC
0, 50; %axis 7 BMt
100,1500; %axis 8 BMl
20, 250; %axis 9 AM
0, 1;] %axis 10 CB
grid on
draft_y = [2, 4, 6, 8];
%
dispS = [4338.433882, 12602.51994, 20397.27172, 29240.4964];
% dispW = [4338.433882, 12602.51994, 20397.27172, 29240.49644];
% %bmT = [49.934497, 18.50834124, 11.99581801, 8.749939429];
KB = [1.69838, 2.41533, 3.48171, 4.66708];
% %LCB = [29.94300827, 29.8
plot(dispW,draft_y, KB,draft_y)
% Compute tick values for each axis to align with main axis
additionalAxisTicks = arrayfun(@(i){linspace(additionalAxisLimits(i,1), ...
additionalAxisLimits(i,2),numel(ax.XTick))}, 1:size(additionalAxisLimits,1));
% Set up multi-line ticks
allTicks = [ax.XTick; cell2mat(additionalAxisTicks')];
tickLabels = compose(repmat('%.2f\\newline',1,size(allTicks,1)), allTicks(:).');
% The %4d adds space to the left so the labels are centered.
% Decrease axis height & width to make room for labels
% Decrease axis height & width to make room for labels
ax.Position(3) = ax.Position(3) * .75; % Reduced width to 75%
ax.Position(4) = ax.Position(4) * .40; % Reduced height to 40%
ax.Position(2) = ax.Position(2) + .48; % move up
% Add x tick labels
set(ax, 'XTickLabel', tickLabels, 'TickDir', 'out')
% Define each row of labels
ax2 = axes('Position',[sum(ax.Position([1,3]))*1.1, ax.Position(2), 0.2, 0]);
linkprop([ax,ax2],{'TickDir','TickLength','FontSize'})
axisLabels = {'Area (m^2)', 'Distance (t)','Area (m^2)','Cnt from 0 (m)','KB (m)'}; % one for each x-axis
set(ax2,'XTick',0.5,'XLim',[0,1],'XTickLabel', strjoin(axisLabels,'\\newline'))
I only tried 2 out of 14
Alpha Boy
on 28 Jul 2020
marked one is not correct!!!, Blue line is ok. how can I plot 14 different scale line??
Adam Danz
on 28 Jul 2020
Edited: Adam Danz
on 28 Jul 2020
You're asking me to do your entire project for you. I can help you learn but I will not do your work for you.
You need to normalize all of your x values so they match the scale of your main x axis.
Here's an example. You need to understand the example and apply it to your data.
First, you need to decide the lower and upper bounds of your x-axis range.
ax.XLim = [4000,30000];
Then you need to normalize the x-values to that range. The x values in my demo range from 20 to 30.
x = [22 30 26 25 24 25 25 22];
xBounds = [20,30];
% Normalize to the x-axis limits
xNorm = (x - xBounds(1))/range(xBounds) * range(ax.XLim) + ax.XLim(1);
Now plot your data using xNorm
plot(xNorm, y)
Repeat this for all lines. The y axis values will automatically adjust with the range of your data.
Alpha Boy
on 28 Jul 2020
xNorm = (x - xBounds(1))/range(xBounds) * range(ax.XLim) + ax.XLim(1); in this line, what does "(1)" mean?
Alpha Boy
on 28 Jul 2020
Sir, Please help me. I am not requesting you to do my project. I simply want to learn. I have stuck with this for last 3 days
Adam Danz
on 28 Jul 2020
"in this line, what does "(1)" mean?"
Look at the value of ax.XLim. The (1) selects the first element which is the lower x-limit.
Normalization is when you convert a set of data to a different scale. A well known example is percentages. 0.2, 0.5, 0.8 can be converted to 20%, 50%, 80% by multiplying by 100. Your normalization is a bit more complicated because the data must be scaled to fit within 4000-30000.
"And where I have to write this codes, I mean which lines? at the end?"
You can normalize the data anywhere in your code after the ax.XLim is set.
I suggest doing the plotting after the axes are all set up.
Adam Danz
on 15 Mar 2022
My answer does not add a second x-axis. Instead, it adds rows of x-tick-labels to represent additional axes at different scales. You could implement this idea but it would not show a second axis line and the tick intervals would differ. Matlab does not currently offer a method of adding addtional axis rulers (lines) but you could ask a new question or search the forum to find work-arounds.
Adila Nalisa Binti Mohd Roslan
on 16 Mar 2022
Thank Adam for claryfication on this issues. However do you have any idea so that I can add second axis like that in Matlab? I would really grateful if you can share the idea. Thank you in advance.
Matthew Mishrikey
on 14 Apr 2022
Note, this method does not work with uiaxes.
Unfortunately the newlines don't get rendered, and you end up with just a single line for each tick label.
This is almost the same code as Adams, with uiaxes, and also forcing the label rotation to 0.
% Set up main axis (on top)
clf()
uif = uifigure('HandleVisibility','on');
ax = uiaxes(uif,'Position', [20 100 500 300]);
ax.XTick = 0:200:2800;
ax.XLim = [0,2800];
% Set axis limits for all other axes
additionalAxisLimits = [...
0, 1400; % axis 2
19.2, 23.4; % axis 3
0.2, 3]; % axis 4
% Compute tick values for each axis to align with main axis
additionalAxisTicks = arrayfun(@(i){linspace(additionalAxisLimits(i,1), ...
additionalAxisLimits(i,2),numel(ax.XTick))}, 1:size(additionalAxisLimits,1));
% Set up multi-line ticks
allTicks = [ax.XTick; cell2mat(additionalAxisTicks')];
tickLabels = compose('%4d\\newline%4d\\newline%.1f\\newline%.1f', allTicks(:).');
% The %4d adds space to the left so the labels are centered.
% You'll need to add "%.1f\\newline" for each row of labels (change formatting as needed).
% Alternatively, you can use the flexible line below that works with any number
% of rows but uses the same formatting for all rows.
% tickLabels = compose(repmat('%.2f\\newline',1,size(allTicks,1)), allTicks(:).');
% Decrease axis height & width to make room for labels
ax.Position(3:4) = ax.Position(3:4) * .75; % Reduced to 75%
ax.Position(2) = ax.Position(2) + .2; % move up
% Add x tick labels
set(ax, 'XTickLabel', tickLabels, 'TickDir', 'out','XTickLabelRotation',0)
% Define each row of labels
ax2 = uiaxes(uif,'Position',[sum(ax.Position([1,3]))*1.08, ax.Position(2), .02, 0.001]);
axisLabels = {'Distance (t)','Area (m^2)','Cnt from 0 (m)','KB (m)'}; % one for each x-axis
set(ax2,'XTick',0.5,'XLim',[0,1],'XTickLabel', strjoin(axisLabels,'\\newline'))
ax2.TickLength(1) = 0.2; % adjust as needed to align ticks between the two axes
linkprop([ax,ax2],{'TickDir','FontSize','XTickLabelRotation'});
Adam Danz
on 14 Apr 2022
Edited: Adam Danz
on 14 Apr 2022
@Matthew Mishrikey thanks for your comment. I recall having this problem in the past but now when I test it with your code in MATLAB R2022a, I don't see the problem. The only change I made was to increase the axes size so I can more clearly see the ticks. I wonder what release of MATLAB you're using.
The tick label rotation became a feature after I added my answer but thanks for the reminder to update my answer to set rotation to 0.
More Answers (0)
See Also
Categories
Find more on Axis Labels in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)