Customizing MATLAB Plots and Subplots

In an economics paper (https://www.federalreserve.gov/econres/feds/files/2018043pap.pdf), all the plots have invisible top axis, with Y-axis values marked on the right hand side with the axis label on top of it, differently from they way MATLAB plots figures in which Y-axis values are marked on the left hand side and axis label is written beside it in a vertical manner.
If you see their figure 9, for instance, which has 4 by 3 subplots, they all share the aforesaid features. More importantly, each individual plot is longer than wider.
THEIR PLOTS
MATLAB PLOTS
I want to generate plots like theirs in MATLAB. I looked around and experimented but couldn't find a solution. Worse, I cannot even figure out which application they have used for all their figures, if it's not MATLAB. Will appreciate any help.

 Accepted Answer

dpb
dpb on 25 Jun 2019
Edited: dpb on 26 Jun 2019
The new(ish) yyaxis function to arbitrarily create two y axes and then switch between left and right axes w/o the need of yyplot to have two separate plot() arguments is useful for such things. As Bjorn says, it's a lot of fine tuning; some of which just can't do with the default Matlab components--like you don't have the flexibility to move axes labels so you'll just have to do them manually.
Here's another very rough starting point---
yyaxis right % create two axes; RH axis has focus
hAx=gca; % get a handle (YAxis property is the two axes handles)
hAx.YAxis(1).TickLabel=[]; % don't show labels on LH axis
set(hAx.YAxis,{'Color'},{'k'}) % use sedate color...
hTx=text(1,1,'Percent of GDP','HorizontalAlignment','right','VerticalAlignment','bottom');
produces
which has most of the features other than the partial box besides the tick marks at the top. You can always simulate this by line if it's important enough.
ADDENDUM
With Steven L's "gotcha!" comment, the above can be generated by using
hRYlab=ylabel('Percent of GDP','Position',[1 1],'HorizontalAlignment','right', ...
'VerticalAlignment','bottom','Rotation',0);
Since it's a Y-axis label, Matlab by default writes it vertically so have to override that with the 'Rotation' parameter even tho is the default for a text() object....
Definitely better to use the axes properties and the access via x/ylabel() functions beats having to go handle-diving inside the axes object for hidden properties from its viewpoint.
My bad for not having carried through and written a label and probed it instead of jumping to the wrong conclusion regarding visibility -- have to admit in 30 yrs, don't know I've ever done anything to an axis label but change font size or the like, though.

12 Comments

Oh...as for the aspect ratio, NB: they have a 3x4 layout of rows x columns whereas yours is 4x3. Moving the labels is only going to make more room horizontally, not vertically; it's the arrangement you'll need to futz with to change the aspect ratio of each plot.
You can always make adjustments to the basic positions to remove extra white space and thus make some minor adjustments, but the basic ratio will be from the layout chosen.
In my very old matlab-version I can change position of titles and xlabels with set and get if you take the text-handle out from title/xlabel - it is a cludgery but possible. Is that removed in you guys' newfangled hg2+ versions?
Good thought, Bjorn! I'd forgetten that since haven't used an HG1 release for quite a long time.
The answer is, they have made much more complex and, unfortunately, also made a lot of things opaque to the end user w/ HG2. This is one--the handle to the tick label text object is now hidden and resides in a second layer.
Searching for hidden properties I found;
>> getundoc(hRYAx)
ans =
struct with fields:
ApplicationData: [1×1 struct]
AxesLayer: 'bottom'
AxesLayerMode: 'auto'
AxesLayer_I: 'bottom'
Axis: 1
AxisMode: 'auto'
Axis_I: 1
Axle: [1×1 LineStrip]
ChildrenMode: 'auto'
Children_I: [0×0 GraphicsPlaceholder]
...
LabelFontSizeMultiplier: 1.1000
LabelFontSizeMultiplierMode: 'auto'
LabelFontSizeMultiplier_I: 1.1000
LabelMode: 'auto'
LabelPosition_IS: 'auto'
Label_I: [1×1 Text]
...
>> hRYTickLabel=hRYAx.Label_I;
>> hRYTickLabel=hRYAx.Label_I
hRYTickLabel =
Text with properties:
String: ''
FontSize: 11
FontWeight: 'normal'
FontName: 'Helvetica'
Color: [0 0 0]
HorizontalAlignment: 'center'
Position: [1.0653 0.5000 0]
Units: 'data'
Show all properties
>>
So, it's still there, just much more difficult to get to. If it's important-enough to OP, could write a function to make getting to and setting stuff more easily done once the hard part is done once.
I think I'll stay with HG1-versions - so this is my getting old moment. Where do I pick up the walking stick and bird-seed?
It's not that difficult to move the label.
x = 0:0.1:1;
plot(x, x.^2);
XL = xlabel('abc');
XL.Position = XL.Position - [0.25 0 0];
There's some additional fine-grained control you can do if you use the Ruler objects stored in the XAxis, YAxis, and ZAxis properties of the axes that contains the plot and the label, but those are a bit of an advanced maneuver.
dpb
dpb on 25 Jun 2019
Edited: dpb on 25 Jun 2019
Dang! Thanks, Steven. One gets so involved in trying to manipulate the axes object, it's too easy to forget the obvious alternative route for labels...is at the label() level instead.
I'd suggest moving to Answer or duplicatiing as an Answer for OP to aid along his journey..
VS
VS on 26 Jun 2019
Edited: VS on 27 Jun 2019
Thank all of you so much and courtesy of your inputs, I have reached closer to what I want to do. Can I number the subplots like the figure in the question, i.e., (a) something (b) something else and so on? It will be nice if I could keep the alignment to the top left just like they have. Is it feasible to write a function which generates all plots and subplots like this with top axis invisible, axis label horizontal on top and all subplots numbered with subplot numbers and titiles aligned to the left? It might save it from being a handicraft work as Bjorn suggested and it will help me everytime I want to generate plots.
You can of course add your subplot-labels to the string in the title
title('(a) subplot-title 1')
though going that way I don't think it is possible to adjust the font (size, weight) of your first '(a)' to something different than the rest of the title-string.
You can use a simple
th = text(xl,yl,'(a)');
and then modify the positions to something typographically pleasing - but: more tweaky-tweaky...
Like I overlooked the obvious with x/ylabel, using text() instead of title() misses out that the title handle is also a title to a text object with all the properties including position, and even interpreter that lets you choose between TeX and LaTeX. Consequently, while not complete freedom regarding word processor kinds of text formatting, one can do quite a lot. The difficult piece for it probably is the line wrap that is not a part of how either title or text behave; you'll have to insert LF at the desired location such as in
hTitle=title(['(a) A Title with' char(10) 'Second line'],'fontweight','normal','fontsize',10);
hTitle.Position=[0 1];
hTitle.HorizontalAlignment='left';
And of course it is possible to write a function to generate all of these automagically once you've gone through the process of customizing one -- simply put the sequence needed into a function with callable parameters for the data and text to be written.
There's a function that's not quite as flexible as I'd like but that will help you.
plot(1:10);
T = title("This is a very long title. " + ...
"I am going to show you how to line wrap it. " + ...
"It may get to be very tall rather than very long.");
Looks pretty messy, doesn't it? Let's wrap it so the lines are 65 characters long then update the title String. [You could wrap before creating the title if you wanted, but I want to show the before versus after.]
S = textwrap({T.String}, 65);
T.String = S;
The textwrap function can accept a uicontrol handle (in which case it'll wrap the text to the width of the control) or a number of columns at which to wrap the text. Ideally it could accept a text object handle in addition to a uicontrol handle; I'll put that in the enhancement database.
Thank you all for your time and input. How do I accept both the answers and is it possible? Should I just click on 'accept'? I ask because both the answers were helpful and I don't want to click on 'accept' for one answer, only to realize that now I cannot 'accept' the other answer.
Don't worry that much about it, accept the most useful and put a vote for the other useful contributions.
More importantly: Pass it on forward. When you see a question or problem you can help with do it!

Sign in to comment.

More Answers (1)

There are contributions on the FEX that facilitate multiple y-axises. This level of figure-tuning often (for me)
turns into a bit of handcraft-work. Something like this might get the axis-locations a few steps toward what you
want:
y = rand(1,7);
[yy1,yy2,yy3] = plotyy(1:7,y,1:7,y);
set(yy3,'color','r')
set(yy1(1),'ycolor','k','yticklabel','','box','off')
set(yy1(2),'ycolor','k')
HTH

2 Comments

Thank you, your answer certainly takes me a step closer to what I want to do -- it hides the top axis and marks the Y-axis values on the right hand side. Can I also do it in a subplot environment, for example, in a 4 by 3 subplot as in the question? Is there anyway I can make all of my subplots longer than wider as in the question figure and have them individually numbered on the top left hand side for each subplot?
See alternate Answer and follow-up comment thereto...
"axes are axes" -- it doesn't make any difference whether they're subplots or not, you treat them the same other than needing to keep the handle to which is which in the array of handles you're (hopefully) saving when you create them.

Sign in to comment.

Products

Asked:

VS
on 25 Jun 2019

Commented:

on 27 Jun 2019

Community Treasure Hunt

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

Start Hunting!