MATLAB: How to loop through each (x,y) pair in MATLAB? [duplicate] - matlab

This question already has an answer here:
How to loop two vectors in MATLAB?
(1 answer)
Closed 4 years ago.
So I want to create a loop in MATLAB where I can retrieve the x,y pairs.
So far, I have two arrays:
x = [x1 x2 x2 x1 x1];
y = [y1 y1 y2 y2 y1];
I would like to create a for loop where I can retrieve pairs (x1,y1), then (x2, y1), then (x2, y2), (x1, y2), and lastly (x1,y1) once again.

This is a trivial loop:
x = [x1 x2 x2 x1 x1];
y = [y1 y1 y2 y2 y1];
for index = 1:numel(x)
pair = [ x(index), y(index) ];
end

In Matlab it is great to be able to avoid loops.
You can build a matrix from your two vectors:
xy = [x;y];
Now every column of xy is a pair. You can then do:
for col_index = 1 : size(xy,2)
xy(:, col_index) % whatever you want to do here
end

Related

Stacking multiple solutions into a single 3D plot

y1=tanh(3*x+5*t);
y2=5*cos(x+3*t);
y3=exp(-x)*sin(2*x+t);
How can I plot y1, y2 and y3 into a single 3D plot for the fixed value of t=0.5?
Assuming yn and x are arrays of values and have been evaluated with t=0.5, the following code will plot all 3 functions on one figure:
figure
plot(x,y1,x,y2,x,y3)
I'm guessing you are additionally asking how to evaluate yn for a range of x. Simply define yn as an array and loop over all values of x:
y1 = [];
x = [1 5 8 17];
t=0.5;
for xi = x
y1 = [y1 ; tanh(3*xi+5*t)];
end

Draw the vector w as well as the projection of another vector onto w

How can I plot the vector w with the projected data onto this vector?
Here is the code - and my trials to plot the weight vector with y1 and y2.
x1=[1 2;2 3;3 3;4 5;5 5] % the first class 5 observations
x2=[1 0;2 1;3 1;3 2;5 3;6 5]
m1 = mean(x1);
m2 = mean(x2);
m = m1 + m2;
d1=x1-repmat(m1,5,1);
d2=x2-repmat(m2,6,1);
c = 0.5.*m;
Sw1 = d1'*d1;
Sw2 = d2'*d2;
Sw = Sw1 + Sw2;
invSw = inv(Sw);
w= invSw*(m1-m2)' %this is my vector projected
scatter(x1(:,1), x1(:,2), 10, 'ro');
hold on;
scatter(x2(:,1), x2(:,2), 10,'bo');
%this is how i plot the decision boundary, but it doesn't seems correct.
quiver(c(1,1), c(1,2), 1, -w(1,1)/w(2,1));
quiver(c(1,1), c(1,2), -1, w(1,1)/w(2,1));
auxw= w/norm(w);
plot([0 auxw(1)], [0 auxw(2)])
hold off;
figure;
y1 = x1*w;
y2 = x2*w;
hist([y1' y2'])
You are very close. You've only calculated (or tried to calculate) the scalar projection or the amount of scale you apply to each vector in order to project each vector in x1 and x2 onto w though what you have is incomplete. If you recall from linear algebra, to determine the scalar projection between two vectors a and b, or the scalar projection of b onto a, the formula is:
Source: Oregon State Mathematics: Calculus for Undergraduates
In our case, a would be w and b would be each of the vectors seen in x1 and x2. I'm assuming each row of these matrices is a vector. The scalar projections are seen in y1 and y2. You need to compute the vector projection, which is defined as taking the scalar projections and multiplying by the unit vectors of a, or simply:
Source: Oregon State Mathematics: Calculus for Undergraduates
Therefore, the calculation of the scalar projections in y1 and y2 are incorrect. You have to multiply by the normalized vector w, then when you find these scalar projection values, you multiply each of these scalar values with the corresponding normalized vector w. However, plotting these all simultaneously on a graph will be confusing. You will have many lines that will overlap onto the original vector w so what I did was I looped through plotting w, a vector in either x1 or x2 and the corresponding projected vector. Each time we loop, we pause and show the data then clear the figure and start again.
As such, I've added and changed the following to your code.
%// Your data
w = [-0.7936; 0.8899];
x1 = [1 2; 2 3; 3 3; 4 5; 5 5];
x2 = [1 0; 2 1; 3 1; 3 2; 5 3; 6 5];
%// Compute scalar projection
auxw = w/norm(w);
s1 = x1*auxw;
s2 = x2*auxw; %// Change for correctness
%// Compute the vector projection
y1 = bsxfun(#times, s1, auxw.');
y2 = bsxfun(#times, s2, auxw.');
%// Place the original vectors and corresponding projections
%// in one matrix
y = [y1; y2];
x = [x1; x2];
%// Loop through and plot w, a point in either x1 or x2
%// and the corresponding projection
for ii = 1 : size(y,1)
plot([0 w(1)], [0 w(2)]);
hold on;
plot([0 y(ii,1)], [0 y(ii,2)], 'r');
plot([0 x(ii,1)], [0 x(ii,2)], 'g');
pause(0.5);
clf;
end
The function bsxfun allows us to multiply each vector in x1 and x2 by their corresponding scalar values. Specifically, it will take the vectors s1 and s2 and when we transpose auxw to be a 1 x 2 vector, we will create new matrices y1 and y2 where each row of either will compute the vector projections of x1 and x2 and place them into the rows of y1 and y2.
The loop at the end cycles through w, a vector in either x1 or x2 and the corresponding projected vector one at a time and we pause for 0.5 seconds each time to see what the results look like. The vector w is in blue, the projected vector is in green and the original vector from either x1 or x2 is in red.
We get these series of figures:
We can see that the red line, which is the projected vector from either x1 or x2 onto w. The green line is the original vector from either x1 or x2.

Mesh Plot Problems in Matlab

I want to draw a meshc contour plot, but the contour is not being drawn as I want.
x = linspace(P(1),P(2)); %// x axis
y = linspace(P(3),P(4)); %// y axis
[X1 Y1] = meshgrid(x,y); %// all combinations of x, y
%[X1,Y1] = meshgrid(1:.125:3);
Z1 = mvnpdf([X1(:) Y1(:)],mu,sigma); %// compute Gaussian pdf
Z2 = reshape(Z1,size(X1)); %// put into same size as X, Y
meshc(X1,Y1,Z2);
%axis([1 3 1 3 -5 10]);
axis([P(1) P(2) P(3) P(4) -5 10])
The code above draws it this way:
But I want it to be this way:
How could I do this?
To get desired distance between the plots you can just subtract some number from the Z2 matrix. I cannot figure out why Matlab divides the plots in this way, but it works:
P = [1 3 1 3];
mu = [2 1.1];
sigma = [.09 .003; ...
.003 .002];
x = linspace(P(1),P(2)); %// x axis
y = linspace(P(3),P(4)); %// y axis
[X1 Y1] = meshgrid(x,y); %// all combinations of x, y
Z1 = mvnpdf([X1(:) Y1(:)],mu,sigma); %// compute Gaussian pdf
Z2 = reshape(Z1,size(X1)); %// put into same size as X1, Y1
Z2 = Z2 - 0.01;
meshc(X1,Y1,Z2);
axis([P(1) P(2) P(3) P(4) -5 10])
Maybe you need to play with other numbers to get a desired result. In my example I subtracted a small number, in order to avoid changing of the pdf-plot range.

Is there a way to graphically add two curves in MatLab?

Lets say I have a sine curve and a cosine curve. Is there any way to add them graphically? Rather than doing sin + cos?
I'm plotting things that are functions of different variables (lets say one curve takes x-values from an array of integers and the other from an array of irrational numbers), so I don't know how else to add them.
Let's say you want to plot y1 = f1(x1) and y2 = f2(x2) you could do this
X = union(x1, x2);
Y1 = interp1(x1, y1, X);
Y2 = interp1(x2, y2, X);
Y = Y1 + Y2;
plot(X, Y)
So to see this in action
x1 = 2 * pi * rand(50, 1);
x2 = 2 * pi * rand(50, 1);
y1 = cos(x1).^2;
y2 = sin(x2).^2;
X = union(x1, x2);
Y1 = interp1(x1, y1, X);
Y2 = interp1(x2, y2, X);
Y = Y1 + Y2;
plot(X, Y)

Show the intersection of two curves

If I have two plots defined by two different equations:
x = 0:0.01:30;
y1 = x .^2 + 2;
y2 = x .^3 ;
and I plot them as
plot(x, y1, x, y2);
How do I get a small ring around the point of intersection programatically (as in the following plot)?
You'll have to find the point of intersection (px, py) manually:
idx = find(y1 - y2 < eps, 1); %// Index of coordinate in array
px = x(idx);
py = y1(idx);
Remember that we're comparing two numbers in floating point representation, so instead of y1 == y2 we must set a tolerance. I've chosen it as eps, but it's up to you to decide.
To draw a circle around this point, you can compute its points and then plot them, but a better approach would be to plot one point with a blown-up circle marker (credit to Jonas for this suggestion):
plot(px, py, 'ro', 'MarkerSize', 18)
This way the dimensions of the circle are not affected by the axes and the aspect ratio of the plot.
Example
x = 0:0.01:30;
y1 = x .^ 2 + 2;
y2 = x .^ 3;
%// Find point of intersection
idx = find(y1 - y2 < eps, 1);
px = x(idx);
py = y1(idx);
figure
plot(x, y1, x, y2, px, py, 'ro', 'MarkerSize', 18)
axis([0 10 0 10])
This should produce the following plot:
In your example, when you have x, y1 and y2
What you can do is
idx = find(abs(y1 - y2) == min(abs(y1 - y2)));
xInter = x(idx)
yInter = y1(idx) % or y2(idx)
If you have x1, y1 and x2, y2, where x1 ~= x2
you could first do 1D interpolation using
yy2 = interp1(x2, y2, x1);
then apply
idx = find(abs(y1 - yy2) == min(abs(y1 - yy2)));
xInter = x1(idx)
yInter = y1(idx) % or yy2(idx)
Excellent post by #EitanT, however I would like to complement this with a different (automated) way to find the intersection (Assuming there is one and the graphs behave nicely).
Here is our starting point:
x = 0:0.01:30;
y1 = x .^2 + 2;
y2 = x .^3 ;
First of all we check whether these values are exactly equal, for non-floating point non-discrete situations this should be sufficient:
idx = find(y1==y2)
If they are never recorded to be exactly equal, an intersection occurs if one surpasses the other, hence we look at the difference:
if isempty(idx)
d = y1-y2;
% At the moment of crossing, the sign will change:
s = diff(sign(d));
% Now just find the point where it changes
f = find(s,1);
end
To summarize this in compact form without additional variables, I would recommend using:
idx = find(y1==y2)
if isempty(idx)
idx = find(diff(sign(y1-y2)),1)
end
Especially when knowing the functions, the symbolic math toolbox can be used.
y1 = x .^2 + 2;
y2 = x .^3 ;
syms x real
intersection=simplify(solve(y1==y2))
Use vpa(intersection) to convert it to a number or double(intersection) to convert it to a floating point value.
Last but not least, perhaps the cleanest way to do this is the command polyxpoly:
[xi,yi] = polyxpoly(x,y1,x,y2)
xi = 1.69560153754948
yi = 4.87508921229275
Good luck!