Add constant values to a column in a table - Matlab - matlab

I wish to add into a table the values of x2 and y2. As both x2 and y2 have a constant values I just wrote x2 value 10 times. Is there a short way to do so which can also be applied on y2 value column?
code:
clc;
clear all;
x1 = [38;43;38;40;49;18;41;58;10;55];
y1 =rot90(11:20);
x2 =[2;2;2;2;2;2;2;2;2;2];
y2 =6;
dTable = table(x1,y1,x2,y2)

You can either use repmat
x1 = [38;43;38;40;49;18;41;58;10;55];
x2 = repmat( 2, 10, 1 ); % 10 rows, 1 column
dTable = table(x1,x2);
Or if you have an existing table, you can assign a constant to an entire column like so
x1 = [38;43;38;40;49;18;41;58;10;55];
dTable = table(x1);
dTable.x2(:) = 2; % Assign all rows of column "x2" to the value 2

Related

How to specifically fprintf an array on a file

Lets say for example we have this array:
x =
0.5920 0.4635
0.6451 0.2118
-0.1206 -0.6036
0.2417 0.4773
0.3029 0.5172
What code would I need to write in order to print in such a way that it looks like this:
coords
x1 0.5920 y1 0.4635
x2 0.6451 y2 0.2118
x3 -0.1206 y3 -0.6036
x4 0.2417 y4 0.4773
x5 0.3029 y5 0.5172
I've tried this:
x = gallery('uniformdata',[1,10],0);
y = gallery('uniformdata',[1,10],1);
[v,c] = voronoin([x(:) y(:)]); %returns an array V with vertices and a cell array C with a matrix for each cell of the diagram.
c
for k = 1 : numel(c)
c{k} = c{k}(c{k} ~= 1)
end
fileID = fopen('cords.txt' , 'w');
for i=1:10
coord = v(c{i},:);
fprintf(fileID,'shape %d:\nx \t y\n', i);
fprintf(fileID,'%.4f %.4f\n', coord(:,1), coord(:,2));
end
fclose(fileID);
but im getting an output like this:
shape 10:
x y
0.5920 0.6451 %notice how the .6451 is on the right side when it should be on the bottom
-0.1206 0.2417
0.3029 0.4635
0.2118 -0.6036
0.4773 0.5172
The fprintf function reads the input variables in a column first manner and sends each value to its appropriate place in the string. So, in your code what happens is that even when you specify two different vectors per %.4f in your code, Matlab ignores that ordering. It puts the first value of coord(:, 1) in the first %.4f and the second value of coord(:, 1) in the second %.4f. Then it breaks the line. Then it again picks up the third value from coord(:, 1) and puts it in the first %.4f and so on. It only picks values from coord(:, 2) when all values of the first vector are exhausted.
The simplest fix is to transpose the coord matrix and then input it to Matlab like this:
fprintf(fileID,'%.4f %.4f\n', coord.'); % .' tranposes the matrix
Edit:
To get the format as x1 0.5920 y1 0.4635, we can make use of the column first ordering that Matlab follows to access a variable
% First we make a new matrix that has each of the required elements for the desired format
% The index of x, the value of x, the index of y and the value of y
tempCoord = [1:size(coord, 1); coord(:, 1).'; 1:size(coord, 1); coord(:, 2).'];
% Now we change the string specification for fprintf
fprintf(fileID,'x%d %.4f y%d %.4f\n', tempCoord);
Why does this work?
If you look at tempCoord, you will see that each of its columns has the format needed for the string specifier, i.e., the index of x, the value of x, the index of y and the value of y
tempCoord =
1.000000000000000 2.000000000000000 3.000000000000000 4.000000000000000 5.000000000000000
0.592000000000000 0.645100000000000 -0.120600000000000 0.241700000000000 0.302900000000000
1.000000000000000 2.000000000000000 3.000000000000000 4.000000000000000 5.000000000000000
0.463500000000000 0.211800000000000 -0.603600000000000 0.477300000000000 0.517200000000000
Now each column becomes each row of the printed file and you get the following output:
x1 0.5920 y1 0.4635
x2 0.6451 y2 0.2118
x3 -0.1206 y3 -0.6036
x4 0.2417 y4 0.4773
x5 0.3029 y5 0.5172

Matlab get symbols from matrix to assign value

I am creating a matrix of symbols and I declare a function using them:
x = syms('x', [1 2]);
f = x(1) + x(2)
So x and f are:
x = [x1 x2];
f = x1 + x2
Now I want to give values to x1 and x2 in a for loop and evaluate f. But when I use:
x(1) = value;
then x becomes:
x = [1 x2]
and x1 is lost, so I cannot evaluate f. How can I assign a value to x1, x2, ..., xn and then evaluate f?
You should use subs like the following:
subs(f,x1,value)
instead of replacing symbol of x1 with a value.
You can see the details of the function here.

Plotting a function with different ranges in Matlab

I would like to plot the following function:
I tried this code:
x = 0:0-1:4;
x1 = x(x<=-1);
x2 = x(x>-1 & x<=2);
x3 = x(x>2);
y1 = -3;
y2 = 1;
y3 = 4;
plot([x1 x2 x3], [y1 y2 y3])
But it is giving me the error that vectors must be the same length. How do I fix this error?
The problem is that matlab do not understand that y1=-3 means -3 for each value of x1. It needs a vector of -3s with as many elements as x1.
One way to define such a vector is the following:
x = -4:0.1:4;
x1 = x(x<=-1);
y1 = -3*ones(1,numel(x1));
So that you can plot the you want in the following way (look at it after giving it a try):
figure;hold on
x = -4:0.1:4;
x1 = x(x<=-1);
y1 = -3*ones(1,numel(x1));
plot(x1,y1)
x2 = x(x>-1 & x<=2);
y2 = ones(1,numel(x2));
plot(x2,y2)
x3 = x(x>2);
y3 = 4*ones(1,numel(x3));
plot(x3,y3)

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.

MATLAB event location to find time required for full conversion of different species

I have a system of ODEs as follows:
dx1/dt = (x1,x2,x3)
dx2/dt = (x1,x2,x3)
dx3/dt = (x1,x2,x3)
The initial conditions are x1=x2=x3=0 # t=0 and the constraints are dx1/dt = 0, dx2/dt = 0, dx3/dt = 0 for x1 = 1, x2 = 1, x3 = 1 respectively. Once x1, x2, x3 reach value of 1 they should remain at 1 for further increase in t.
I need to find out (1) x1, x2, x3 at different t and (2) estimate the values of t when each of them becomes 1. I had difficulty in getting ressults for (2).
I tried to use the following event function:
function [val,stop,dir] = event(t,X)
X1 = x1;
X2 = x2;
X3 = x3;
val = [X1 -1; X2 -1; X3 -1];
stop= [1;1;1];
dir = [1;1;1];
end
It did not work. Then I tried another code to at least find t corresponding to x3 = 1 (because x3 increases slowly compared to x1 and x2).
function [val,stop,dir] = event(t,X)
X3 = x3;
val = X3 -1;
stop= 1;
dir = 1;
end
Could anyone guide me in this regard?
With regards.
Sudip
This looks like pretty straightforward to solve with the ode solvers, without the need for event. I would define a function such as:
function dX = my_ode(t,X)
for k=1:length(X)
if abs(X(k)-1) <= 1e-6 % or use whatever tolerance you want, e.g. eps
dX(k) = 0;
else
dX(k) = X(k);
end
end
I would then call the ode solver as follows:
tspan = [0 10]; % choose whatever time span you want
X_init = [0 0 0];
[T,X] = ode45(#my_ode,tspan,X_init);
plot(T,X)
Not sure why you have the Simulink tag, but that's also easily implemented in Simulink if need be.