How to get variable scales on y axis for same graph in matlab plotting? - matlab

I am working on matlab programming, my problem is that in the same graph on y axis i need to have variable scaling, for example from 0.1 to 1 i need to have a gap between scales 0.1, but after 1 I need to have scale gap of 2, is there some command available for the same?

There is an example by The Mathworks on Matlab answers which does pretty much what you want to achieve. The idea is to create 2 axes on the same figure and use one axes to plot some data (eg. for the 0.1:0.1:1 tick marks) and the rest on the other axes. Then you overlay both axes with a transparent background:
%Create two overlapping axes
axes_handle_1 = axes;
axes_position = get(axes_handle_1, 'Position');
axes_handle_2 = axes('Position', axes_position);
%Create some data with a large gap in the x domain
my_x_data = [1:10 25:35];
my_y_data = rand(1, length(my_x_data));
%Plot the two sections of data on different axes objects
plot(axes_handle_1, my_x_data(1:10), my_y_data(1:10))
plot(axes_handle_2, my_x_data(11:end), my_y_data(11:end))
%Link the y axis limits and fontsize property of the axes objects
linkaxes([axes_handle_1 axes_handle_2], 'y');
linkprop([axes_handle_1 axes_handle_2], 'FontSize');
%Set the x range limits and tick mark positions of the first axes object
set(axes_handle_1, 'XLim', [1 21], ...
'XTick', [1 5 10])
%Set the x range limits and tick mark positions for the second axes object.
%Also set the background color to 'none', which makes the background
%transparent.
set(axes_handle_2, 'Color', 'none', ...
'YTickLabel', [], ...
'XLim', [14 35], ...
'XTick', [25 30 35])
It's quite straightforward and to my knowledge there is no built-in way to do it otherwise, except maybe with submissions from the File Exchange. Anyhow if you have questions about the above code please ask!

Please use gca property of matlab. In gca you can set a variable as your scales. Make that variable by merging two different scales
x=[1:80];
y=[.1:.1:8];
figure
plot(x,y);
%First Scale
scale1=[.1:.1:1];
%New scale is being started from 3. If we start from 1, 1 will be repeated
scale2=[3:2:9];
%Merging two variables scale1 and scale2
set(gca,'YTick',[scale1 scale2]);
Please refer http://www.mathworks.in/help/matlab/creating_plots/change-tick-marks-and-tick-labels-of-graph.html

You can also try the idea of scaling one dataset so that it has a similar magnitude as the other data set. Here you can multiply one dataset by 100 (or any suitable scaling parameter), and then it will be similar in size to the other data set. In order to clearly mention which data has been scaled in the graph use the legend.
plot(x,data1,x,100*data2)
legend('data1','100*data2','location','southeast')
Hope this helps.

Related

How to control the default distance between ticks of the Y axis?

Here is a simple MATLAB code. How to control the default distance between ticks of the Y axis? I want to make it smaller to fit in my paper. Hint: I update the post with 2 picture that shows what I mean (they are the same but the distance between the y axis ticks is smaller in one picture that the other.
x = linspace(-10,10,200);
y = sin(4*x)./exp(x);
plot(x,y)
xlim([0 10])
ylim([-0.4 0.8])
You can control the tick by using the gca object of the plot. Here is an example for xtick. Change 'xtick' to 'ytick':
plot(x,y);
set(gca, 'xtick', [-10:2:10]);
If you want to change the x-axis tick labels with new labels, then you can change the values of the labels as follows:
% specify the ticks first where you want to change
xticks([0 2 4 6 8])
% change the corresponding labels to the required ones
xticklabels({'-1', '-2', '-3', '-4', '-5'})
You can modify the height of the graph, maintaining the number and values of the tick marks, which makes the distance between tick marks smaller.
To do so, set the figure window’s 'Position' property (this is equivalent to dragging the edges of the window to make the figure smaller), and setting the locations of the tick marks manually to prevent MATLAB from reducing their number. For example:
h = gcf; % figure handle
a = gca; % axes handle
ticks = get(a,'YTick');
pos = get(h,'Position');
pos(4) = pos(4) * 0.75; # reduce the size
set(h,'Position',pos);
set(a,'YTick',ticks)
You should also note the PaperPosition, PaperSize and other Paper... properties of the figure, as they are used when printing (also to file). You might want to manually set those properties before creating a PDF or EPS from the graph.
Here is even a simpler way then what #Cris suggested:
ax = axes;
ax.YTickMode = 'manual';
ax.Position(4) = ax.Position(4)*0.75;
by setting the YTickMode to manual you prevent Matlab from updating the ticks upon resizing of the axes. Then you change the hight of the axes by setting the position property directly.

Hold on only the axis, not the data

I want my graph to fixed axes and also plot the data one by one. Everything is already known, however if i use hold off to remove the first set of data, it also forgets the limits on the axes and automatically assigns new limits for the second set of data.
Is it somehow possible to keep the axes the same for each time a separate data piece is plotted in the same figure?
code for now is:
figure(4)
grid on
axis([xL yL zL])
for j = 1:n % n is amount of data sets
for i = 1:2 % two items drawn per data set
*plot data*
hold on
end
%This part has to be done every iteration again in order to make it work now
axis([xL yL zL])
xlabel = ...
ylabel
zlabel
title
pause(tstop)
hold off
end
after some searching the only relevant topic i found was; Matlab: Plot a subplot with hold on and hold off in a loop without always calling xlabel, ylabel, xlim, etc
However i do not understand it at all. It uses a parent figure, replacechildren, nextplot and such which i am not familiar with and also cant find much information about.
Here's an example that can be easily adapted to your needs:
xlim([0 10]) %// set x-axis limits
ylim([0 10]) %// set y-axis limits
set(gca,'nextplot','replacechildren') %// prevent axis limits from changing with
%// each new plot
plot(3:8,3:8); %// note axis limits are kept as [0 10]
pause(1)
plot(5:7,5:7); %// note axis limits are kept as [0 10]

plotting two figures using matlab plotyy

I am struggling to draw my two plots, one is a simple x=y and the other is a boxplot using plotyy. Here are the two :
h1=boxplot(box_panda_8(:, [8 16 24 32 128]) ,'symbol','','notch','on','whisker',0.3)
and
h2=plot([0 5],[0 5], 'k--')
given that i am defining the x axis as
x= 0:5
why the plotyy goes wrong (returns not enough input)
plotyy(x,h1,x,h2)
Updated question
Tackling the issue with two separate plots using axes:
%%% two y axes
y2 = 1:6;
x2 = 1:6;
% Plot the first data set
hl1 = boxplot(box_panda_8(:, [8 16 24 32 48 128]) ,'symbol','','notch','on','whisker',0.3)
% Get the axes and configure it
ax1 = gca;
set(ax1,'XColor','r','YColor','r')
%Create the new axes
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','top',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k','YColor','k');
% Plot the second data set with the new axes
hl2 =plot(x2,y2,'Color','k','parent',ax2);
but still I dont get my final plot in a right way.
plotyy() is not for merging plots together. Take a look at the documentation for plotyy().
[AX,H1,H2] = plotyy(X1,Y1,X2,Y2,'function1','function2')
Uses function1(X1,Y1) to plot the data for the left axis and function2(X2,Y2) to plot the data for the right axis. So you should be able to do what you're looking for by doing something along these lines:
[AX,H1,H2] = plotyy(boxplot_x,lineplot_x,lineplot_y,#boxplot,#plot);
You can use set() with AX(1) and AX(2) to change axes properties (like titles, labels, tickmarks etc.) for the left and right axis, respectively. You can use set() with H1 and H2 to set line properties for your boxplot and line plot, respectively.
Unfortunately I do not have the stats toolbox so I'm unable to test whether or not this syntax will work for boxplot().
It is also worth noting that plotyy() can be quite annoying to work with, and is limited to two plots. By stacking axes in the same figure with the backgrounds off, you remove this limitation and gain user friendly control over all aspects of each plot. See this question for a basic example.

How to plot arrow with data coordinates in Matlab?

I know there is a function named annotation can plot arrows or double arrows. But annotation can only plot in normalized unit. For example:
annotation('arrows',[x1 x2],[y1 y2])
Here, [x1, x2] should be a ratio number less than one.
So, my question is how can I plot arrows with a true value rather than a normalized value?
I wonder if there is any other function can approach this or is there any function I can get the axis value of the figure so that I can adjust the true value into a normalized value.
For the positioning of annotations, Matlab offers the function dsxy2figxy to convert data space points to normalized space coordinates. However, for whatever reasons, the function is not included in the Matlab distribution and has to be "created" first.
Copy the following line into the command window and execute it to open the function in your editor.
edit(fullfile(docroot,'techdoc','creating_plots','examples','dsxy2figxy.m'))
To use the function dsxy2figxy save it somewhere in your matlab search path.
Please find the full instructions for the function dsxy2figxy at matlab-central: http://www.mathworks.de/help/techdoc/creating_plots/bquk5ia-1.html
Even though annotation uses normalized as default units, you can associate these objects to the current axes (gca) and use data units for setting X and Y properties.
Here is an example of plotting a single arrow.
plot(1:10);
ha = annotation('arrow'); % store the arrow information in ha
ha.Parent = gca; % associate the arrow the the current axes
ha.X = [5.5 5.5]; % the location in data units
ha.Y = [2 8];
ha.LineWidth = 3; % make the arrow bolder for the picture
ha.HeadWidth = 30;
ha.HeadLength = 30;
For anyone who comes across this topic looking to draw arrows in "data space" rather than in units relative to the figure and/or axes, I highly recommend arrow.m from the file exchange.
I've just discovered this method, since I don't want to have to bother with normalised units. Use the latex interpreter:
figure
plot([1:5],[1:5]*3,'.-')
%// Say I want to put an arrow pointing to the location, [3 9]
text(2.94,8.3,'\uparrow','fontsize',20)
text(2.8,7.8,'point [3,9]')
To make the arrow longer, use a larger fontsize.
Pros
Easier, faster and quicker than using normalised units
Don't need to install any functions (good for us lazy people..)
making use of the LaTeX interpreter, there is a whole range of arrows (up, down, left, right and other angles (see Symbol list)
Cons
Definitely needs trial and error/tweaking to get the correct location of the arrow head relative to the POI.
There is limited control over the length of the arrow
Some latex commands aren't understood by the interpreter (boo).
If I remember correctly you need to calculate the position of the axes in relation to the figure.
it should go like:
%% example plot
clf
plot(rand(5,2)*5)
%% get info specific to the axes you plan to plot into
set(gcf,'Units','normalized')
set(gca,'Units','normalized')
ax = axis;
ap = get(gca,'Position')
%% annotation from 1,2 to 3,4
xo = [1,3];
yo = [2,4];
xp = (xo-ax(1))/(ax(2)-ax(1))*ap(3)+ap(1);
yp = (yo-ax(3))/(ax(4)-ax(3))*ap(4)+ap(2);
ah=annotation('arrow',xp,yp,'Color','r');
Note Fixed offset in original calculation - ap(3),ap(4) are width and height of gca, not corner positions
After creating the annotation object you should set the property Units to an absolute one. Example:
arrowObj = annotation('arrow', [0.1 0.1], [0.5 0.5]);
set(arrowObj, 'Units', 'centimeters');
set(arrowObj, 'Position', [1 1 3 5]);
One approach would be to define an arrowhead in the axis units:
Ax=[0 -0.003 0.003 0]; % (Ax,Ay) form an upward pointing arrowhead.
Ay=[0.01 0.0060 0.0060 0.01];
Ax=Ax-mean(Ax); % center it on zero
Ay=Ay-mean(Ay);
Then at desired arrowhead index in on a curve vv, compute
x1=vv(in,1); y1=vv(in,2);
x2=vv(in+1,1); y2=vv(in+1,2);
u=x2-x1;
v=y2-y1;
th=-pi/2+atan2(v,u);
R=[cos(th) -sin(th); sin(th) cos(th)]; % Rotation matrix for local slope of vv.
A=R*[Ax;Ay]; % Rotate the arrowhead.
patch(x1+A(1,:),y1+A(2,:),'r','LineWidth',0.01) % plot rotated arrowhead at (x1,y1).
plot(x1+A(1,:),y1+A(2,:),'r','LineWidth',0.01) % Kludge to make boundary red too (I'm sure there is a more elegant way).
Worked for me, for my particular circumstances.
You can use the 'arrow' component in the (well-documented) DaVinci Draw toolbox (full disclosure: I wrote/sell the toolbox, though arrows are free).
Example syntax and example output are below.
davinci( 'arrow', 'X', [0 10], 'Y', [0 2], <plus-lots-of-options> )

How to make 1-D plots in MATLAB?

How can I make plots in MATLAB like in below?
I won't need labels, so you can ignore them. I tried using normal 2D plot, by giving 0 to y parameter for each data points. It does help, but most of the plot remains empty/white and I don't want that.
How can I solve this problem?
Edit:
This is how I plot(playing with values of ylim does not help):
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
title('LDA 1D Plot');
ylim([-0.2 0.2]);
hold off
One way to do this would be to adjust the 'XLim', 'YLim', and 'DataAspectRatio' properties of the axes so that it renders as essentially a single line. Here's an example:
data1 = rand(1,20)./2; %# Sample data set 1
data2 = 0.3+rand(1,20)./2; %# Sample data set 2
hAxes = axes('NextPlot','add',... %# Add subsequent plots to the axes,
'DataAspectRatio',[1 1 1],... %# match the scaling of each axis,
'XLim',[0 1],... %# set the x axis limit,
'YLim',[0 eps],... %# set the y axis limit (tiny!),
'Color','none'); %# and don't use a background color
plot(data1,0,'r*','MarkerSize',10); %# Plot data set 1
plot(data2,0,'b.','MarkerSize',10); %# Plot data set 2
And you will get the following plot:
Here's one way to reproduce your figure using dsxy2figxy and annotate. dsxy2figxy can be hard to find the first time, as it is not really in your path. It is part of the MATLAB package and is provided in the example functions. You can reach it by searching for it in the help docs and once you find it, open it and save it to a folder in your path.
h1=figure(1);clf
subplot(4,1,1);
hold on
xlim([0.2,1]);ylim([-1,1])
%arrow
[arrowX,arrowY]=dsxy2figxy([0.2,1],[0,0]);
annotation('arrow',arrowX,arrowY)
%crosses
x=[0.3,0.4,0.6,0.7,0.75];
plot(x,0,'kx','markersize',10)
%pipes
p=[0.5,0.65];
text(p,[0,0],'$$\vert$$','interpreter','latex')
%text
text([0.25,0.5,0.65],[1,-1,-1]/2,{'$$d_i$$','E[d]','$$\theta$$'},'interpreter','latex')
axis off
print('-depsc','arrowFigure')
This will produce the following figure:
This is sort of a hackish way to do it, as I've tricked MATLAB into printing just one subplot. All rasterized formats (jpeg, png, etc) will not give you the same result, as they'll all print the entire figure including where the non-declared subplots should've been. So to get this effect, it has to be an eps, and it works with it because eps uses much tighter bounding boxes... so all the meaningless whitespace is trimmed. You can then convert this to any other format you want.
Ok so the closest I have come to solving this is the following
hax = gca();
hold on
for i=1:120
if genders(v_labels(i)) == CLASS_WOMAN
plot(v_images_lda(i,:) * w_lda,0,'r*');
else
plot(v_images_lda(i,:) * w_lda,0,'b.');
end
end
set(hax, 'visible', 'off');
hax2 = axes();
set(hax2, 'color', 'none', 'ytick', [], 'ycolor', get(gcf, 'color');
pos = get(hax, 'position');
set(hax2, 'position', [pos(1), pos(2)+0.5*pos(4), pos(3), 0.5*pos(4)]);
title('LDA 1D Plot');
hold off
So in short, I hid the original axis and created a new one located at 0 of the original axis, and as I couldn't remove the y axis completely I set it's color to the background color of the figure.
You can then decide if you also want to play with the tick marks of the x-axis.
Hope this helps!
Very naive trick but a useful one.
Plot in 2d using matlab plot function. Then using edit figure properties compress it to whichever axis you need a 1D plot on !! Hope that helps :)