Matlab: how to remove extra y axis generated by 'axes'? - matlab

I am now having trouble plotting something by matlab.
x1 = 1:2500;
y1 = 1:2500:2500^2;
y2 = 1:2400:2500*2400;
figure
subplot(2,2,1);
semilogy(x1, y1, '-', x1, y2, '-.');
set(gca,'xticklabel',{[]});
pp = subplot(2,2,2);
pospp = get(pp, 'Position');
ax3 = axes('Position',pospp);
ax4 = axes('Position',[0.7 0.7 0.1 0.1]);
axes(ax3);
semilogy(x1, y1, '-', x1, y2, '-.');
set(gca,'xticklabel',{[]});
axes(ax4);
semilogy(2000:2500, y1(2000:2500), '-', 2000:2500, y2(2000:2500), '-.');
set(ax3,'xticklabel',{[]});
set(ax4,'xticklabel',{[]});
Here is the figure
I am wondering how can I remove one y axis from the right subplot? The one with "0, 0.2, 0.4, 0.6, 0.8, 1.0"? I only want to keep the log-scale one.
Thank you.

In this line:
ax3 = axes('Position',pospp);
you create an extra axes object. Remove this line and the axes will be gone. Use pp instead of ax3.

Related

Change the legend of a Matlab figure

I would like to change the legend style of the following picture generated in Matlab:
x1=-5;
x2=5;
y1=-5;
y2=5;
x = [x1, x2, x2, x1, x1];
y = [y1, y1, y2, y2, y1];
fill(x,y,'b')
legend('A')
As you can see the legend displays a blue rectangle. What I would like is a filled blue circle in place of the rectangle as if the picture was generated as a scatter plot. How can I obtain that?
I would suggest to add a fictive value with hold on; p = plot(NaN, NaN, 'b.', 'MarkerSize', 15); then legend this specific "fake" plot with: legend(p, 'A');
x1=-5;
x2=5;
y1=-5;
y2=5;
x = [x1, x2, x2, x1, x1];
y = [y1, y1, y2, y2, y1];
fill(x,y,'b');
hold on; p = plot(NaN, NaN, 'b.', 'MarkerSize', 15);
legend(p, 'A')
#Bebs has a nice solution.
Another suggest is to change directly the legend icon:
[a,b] = legend('A');
b(2).Xdata = sin(-pi:0.1:pi)/10+0.4; % you can play with numbers to set size and location of circle
b(2).Ydata = cos(-pi:0.1:pi)/5+0.5;
Now you can set some other properties:
b(2).LineWidth = 1; % thicker line
b(2).FaceColor = [1 1 1]; % white fill
b(2).EdgeColor = [0 0 1]; % blue edge

How to create three Y-axis in one graph? [duplicate]

I have 4 sets of values: y1, y2, y3, y4 and one set x. The y values are of different ranges, and I need to plot them as separate curves with separate sets of values on the y-axis.
To put it simple, I need 3 y-axes with different values (scales) for plotting on the same figure.
Any help appreciated, or tips on where to look.
This is a great chance to introduce you to the File Exchange. Though the organization of late has suffered from some very unfortunately interface design choices, it is still a great resource for pre-packaged solutions to common problems. Though many here have given you the gory details of how to achieve this (#prm!), I had a similar need a few years ago and found that addaxis worked very well. (It was a File Exchange pick of the week at one point!) It has inspired later, probably better mods. Here is some example output:
(source: mathworks.com)
I just searched for "plotyy" at File Exchange.
Though understanding what's going on in important, sometimes you just need to get things done, not do them yourself. Matlab Central is great for that.
One possibility you can try is to create 3 axes stacked one on top of the other with the 'Color' properties of the top two set to 'none' so that all the plots are visible. You would have to adjust the axes width, position, and x-axis limits so that the 3 y axes are side-by-side instead of on top of one another. You would also want to remove the x-axis tick marks and labels from 2 of the axes since they will lie on top of one another.
Here's a general implementation that computes the proper positions for the axes and offsets for the x-axis limits to keep the plots lined up properly:
%# Some sample data:
x = 0:20;
N = numel(x);
y1 = rand(1,N);
y2 = 5.*rand(1,N)+5;
y3 = 50.*rand(1,N)-50;
%# Some initial computations:
axesPosition = [110 40 200 200]; %# Axes position, in pixels
yWidth = 30; %# y axes spacing, in pixels
xLimit = [min(x) max(x)]; %# Range of x values
xOffset = -yWidth*diff(xLimit)/axesPosition(3);
%# Create the figure and axes:
figure('Units','pixels','Position',[200 200 330 260]);
h1 = axes('Units','pixels','Position',axesPosition,...
'Color','w','XColor','k','YColor','r',...
'XLim',xLimit,'YLim',[0 1],'NextPlot','add');
h2 = axes('Units','pixels','Position',axesPosition+yWidth.*[-1 0 1 0],...
'Color','none','XColor','k','YColor','m',...
'XLim',xLimit+[xOffset 0],'YLim',[0 10],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
h3 = axes('Units','pixels','Position',axesPosition+yWidth.*[-2 0 2 0],...
'Color','none','XColor','k','YColor','b',...
'XLim',xLimit+[2*xOffset 0],'YLim',[-50 50],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
xlabel(h1,'time');
ylabel(h3,'values');
%# Plot the data:
plot(h1,x,y1,'r');
plot(h2,x,y2,'m');
plot(h3,x,y3,'b');
and here's the resulting figure:
I know of plotyy that allows you to have two y-axes, but no "plotyyy"!
Perhaps you can normalize the y values to have the same scale (min/max normalization, zscore standardization, etc..), then you can just easily plot them using normal plot, hold sequence.
Here's an example:
%# random data
x=1:20;
y = [randn(20,1)*1 + 0 , randn(20,1)*5 + 10 , randn(20,1)*0.3 + 50];
%# plotyy
plotyy(x,y(:,1), x,y(:,3))
%# orginial
figure
subplot(221), plot(x,y(:,1), x,y(:,2), x,y(:,3))
title('original'), legend({'y1' 'y2' 'y3'})
%# normalize: (y-min)/(max-min) ==> [0,1]
yy = bsxfun(#times, bsxfun(#minus,y,min(y)), 1./range(y));
subplot(222), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('minmax')
%# standarize: (y - mean) / std ==> N(0,1)
yy = zscore(y);
subplot(223), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('zscore')
%# softmax normalization with logistic sigmoid ==> [0,1]
yy = 1 ./ ( 1 + exp( -zscore(y) ) );
subplot(224), plot(x,yy(:,1), x,yy(:,2), x,yy(:,3))
title('softmax')
Multi-scale plots are rare to find beyond two axes... Luckily in Matlab it is possible, but you have to fully overlap axes and play with tickmarks so as not to hide info.
Below is a nice working sample. I hope this is what you are looking for (although colors could be much nicer)!
close all
clear all
display('Generating data');
x = 0:10;
y1 = rand(1,11);
y2 = 10.*rand(1,11);
y3 = 100.*rand(1,11);
y4 = 100.*rand(1,11);
display('Plotting');
figure;
ax1 = gca;
get(ax1,'Position')
set(ax1,'XColor','k',...
'YColor','b',...
'YLim',[0,1],...
'YTick',[0, 0.2, 0.4, 0.6, 0.8, 1.0]);
line(x, y1, 'Color', 'b', 'LineStyle', '-', 'Marker', '.', 'Parent', ax1)
ax2 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','left',...
'Color','none',...
'XColor','k',...
'YColor','r',...
'YLim',[0,10],...
'YTick',[1, 3, 5, 7, 9],...
'XTick',[],'XTickLabel',[]);
line(x, y2, 'Color', 'r', 'LineStyle', '-', 'Marker', '.', 'Parent', ax2)
ax3 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','g',...
'YLim',[0,100],...
'YTick',[0, 20, 40, 60, 80, 100],...
'XTick',[],'XTickLabel',[]);
line(x, y3, 'Color', 'g', 'LineStyle', '-', 'Marker', '.', 'Parent', ax3)
ax4 = axes('Position',get(ax1,'Position'),...
'XAxisLocation','bottom',...
'YAxisLocation','right',...
'Color','none',...
'XColor','k',...
'YColor','c',...
'YLim',[0,100],...
'YTick',[10, 30, 50, 70, 90],...
'XTick',[],'XTickLabel',[]);
line(x, y4, 'Color', 'c', 'LineStyle', '-', 'Marker', '.', 'Parent', ax4)
(source: pablorodriguez.info)
PLOTYY allows two different y-axes. Or you might look into LayerPlot from the File Exchange. I guess I should ask if you've considered using HOLD or just rescaling the data and using regular old plot?
OLD, not what the OP was looking for:
SUBPLOT allows you to break a figure window into multiple axes. Then if you want to have only one x-axis showing, or some other customization, you can manipulate each axis independently.
In your case there are 3 extra y axis (4 in total) and the best code that could be used to achieve what you want and deal with other cases is illustrated above:
clear
clc
x = linspace(0,1,10);
N = numel(x);
y = rand(1,N);
y_extra_1 = 5.*rand(1,N)+5;
y_extra_2 = 50.*rand(1,N)+20;
Y = [y;y_extra_1;y_extra_2];
xLimit = [min(x) max(x)];
xWidth = xLimit(2)-xLimit(1);
numberOfExtraPlots = 2;
a = 0.05;
N_ = numberOfExtraPlots+1;
for i=1:N_
L=1-(numberOfExtraPlots*a)-0.2;
axesPosition = [(0.1+(numberOfExtraPlots*a)) 0.1 L 0.8];
if(i==1)
color = [rand(1),rand(1),rand(1)];
figure('Units','pixels','Position',[200 200 1200 600])
axes('Units','normalized','Position',axesPosition,...
'Color','w','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'NextPlot','add');
plot(x,Y(i,:),'Color',color);
xlabel('Time (s)');
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
else
color = [rand(1),rand(1),rand(1)];
axes('Units','normalized','Position',axesPosition,...
'Color','none','XColor','k','YColor',color,...
'XLim',xLimit,'YLim',[min(Y(i,:)) max(Y(i,:))],...
'XTick',[],'XTickLabel',[],'NextPlot','add');
V = (xWidth*a*(i-1))/L;
b=xLimit+[V 0];
x_=linspace(b(1),b(2),10);
plot(x_,Y(i,:),'Color',color);
ylab = strcat('Values of dataset 0',num2str(i));
ylabel(ylab)
numberOfExtraPlots = numberOfExtraPlots - 1;
end
end
The code above will produce something like this:

Multiple plots on same figure

x = [0.35, 0.65, 0.8, 1]
y1 = [0.1, 0.21, 0.29, 0.35]
y2 = [0.11, 0.26, 0.28, 0.39]
y3 = [0.1, 0.2, 0.28, 0.36]
y4 = [0.1, 0.25, 0.31, 0.37]
I need to plot all this data on the same graph, such that there is one x-axis and two y-axes, one on the left and one on the right. The interval for y-axes is 0.1:0.1:0.4, and that for x-axis is 0:0.1:1.
I have tried plotyy:
[ax, h1, h2] = plotyy(x, y2, x, y4);
hold on
[bx, h3, h4] = plotyy(x, y3, x, y1);
but one of the vectors does not plot on the same graph. When you run this, and use the PAN option on the graph, you'll realize that only 3 curves are plotted while the 4th curve is plotted on another figure. When I check the legend U get only 3 curves, and not 4.
How about something like this:
plot(x, [y1(:) y2(:) y3(:) y4(:)])
legend({'y1' 'y2' 'y3' 'y4'}, 'Location','NorthWest')
set(gca, 'XLim',[0 1], 'YLim',[0.1 0.4])
Skip the hold and use
[ax, h1, h2] = plotyy(x, [y2;y3], x, [y4;y1]);
Edit:
This is kind of a hack since it is does not support data sets were x differ. That is y2 and y3 should be specified for the same x. The same is true for y4 and y1.

yticks does not show correctly when mixing plotyy and semilogy in matlab

I am plotting two curves in different axes in the same figure with plotyy. The first curve ranges from 10^-4 to 10^-1 and the second curve ranges from 0 to 10. If I plot in the following way,
[AX, H1, H2] = plotyy(x, y1, x, y2, 'semilogy', 'semilogy');
They will both plotted as semilogy and with correct scale in y. But I don't want to show y2 in log10 scale, so I change
[AX, H1, H2] = plotyy(x, y1, x, y2, 'semilogy', 'plot');
However, then on left and right y axis, the tick only show the min and max range, all detail inbetween gone. Why's that?
You can try this:
[AX, H1, H2] = plotyy(x, y1, x, y2, 'semilogy', 'plot');
% set yticks for the left axis
set(AX(1), 'ytick', yourDesiredYticks1)
set(AX(1), 'box', 'off') % to remove corresponding yticks on the right side of the plot
% set yticks for the right axis
set(AX(2), 'ytick', yourDesiredYticks2)
set(AX(2), 'box', 'off')
Try this:
%# create some data resembling what you described
x = 1:100;
y1 = rand(size(x))*1e-1 + 1e-4;
y2 = rand(size(x))*10;
%# plot
hAx = plotyy(x,y1, x,y2, 'semilogy', 'semilogy');
set(hAx(2), 'YScale','linear')

Plotting a line above/below existing lines created with plotyy

I'm running this code:
t = linspace(0, 10, 1000);
y1 = 2*t;
y2 = 3*t;
figure;
[ax, h1, h2] = plotyy(t, y1, t, y2);
set(h1, 'LineWidth', 4);
set(h2, 'LineWidth', 4);
hold on;
h3 = plot([5, 5], [0, 3000], 'LineWidth', 6, 'Color', [0.6, 0.6, 0.6]);
Which creates this plot:
Notice how the vertical grey line appears on top of the blue line (y1) but below the green line (y2).
How do I plot the grey line either on top of the other two lines, or below the other two lines?
I see two options:
A. Bring the gray line forward by moving it to the second axes created by the plotyy command
set(h3,'parent',ax(2));
B. Place the gray line on the bottom by rearranging the order of the blue and grey lines on
the axes.
chld = [h1 h3];
set(ax(1),'children',chld); %# reorders the two lines so that the gray line is in back.
To make the gray line bottom, you can also change the order of drawing.
t = linspace(0, 10, 1000);
y1 = 2*t;
y2 = 3*t;
figure;
h3 = plot([5, 5], [0, max(y1)], 'LineWidth', 6, 'Color', [0.6, 0.6, 0.6]);
hold on;
[ax, h1, h2] = plotyy(t, y1, t, y2);
set(h1, 'LineWidth', 4);
set(h2, 'LineWidth', 4);
There's a trick in h3 = plot(...) to make sure the left scale is correct, though.