Windowed subtraction of vectors that are not same size and then finding the mean of results - matlab

Good day,
I have a question what I want to achieve without the loop if possible. As title says I need to do windowed subtraction of vectors that are not same size and then finding the mean of results.
As example, let say that we have vector a = [2 3 4 5 6] and vector b = [1 2].
Program will have to move window with smaller numbers of elements (in this example vector b) over bigger one (vector a) and make operations on that way so it starts in first two elements in vector a and make subtraction with vector b and then sum results and find mean.
In this example it will just make calculation of subtraction 2-1 = 1, 3-2 = 1, summing results 1+1=2 and divide them with 2 (because vector b is that size). Final result is 1.
Then we move window on second elements of vector a (value 3 and 4 there, or index 2 and 3) and repeat process to the last elements of vector a.
For final result we need to get vector c who consist of elements [1 2 3 4] for this example.
Is this possible to do without looping because I have data sets over 10k of size. Thanks in advance

I can solve it with only one loop, iterating through "b" (two loops in your example).
Declare vectors (as columns! This is needed for matlabs computations to work)
a = [2 3 4 5 6]';
b = [1 2]';
Declare matrix for computed results. Each column represents subtractions of elements in "a" with one of the elements in "b".
c = zeros(length(a)-length(b)+1,length(b));
for k = 1:length(b)
c(:,k) = a(k:length(a)-length(b)+k)-b(k);
end
Now just sum the elements in "c" row wise and divide by length of "b" to get the mean
result = sum(c,2)/length(b);
You can simplify this for your exact example, but this is a generic solution for any vetors "a" and "b", where "b" is the smaller vector.

Related

Sum of multiplication of unequal vectors

I have two vectors:
a = [1 2 3 4 5]
b = [1; 2]
Every element in a will multiply to every element in b. The sum of the result is the final output. i.e.
a(1)*b(1)+a(1)*b(2)
a(2)*b(1)+a(2)*b(2)
a(3)*b(1)+a(2)*b(2)
a(4)*b(1)+a(4)*b(2)
a(5)*b(1)+a(5)*b(2)
The code should remain applicable to a large size vector. Is it possible to code without for loop?
That's normal matrix multiplication combined with sum.
sum((b * a).', 2) %I'll prefer this since it uses one less transpose
or
sum(a.' * b.', 2)

1) Extract submatrices, 2) vectorize and then 3) put back

I simplify my problem, let says I have three matrices.
I want to extract the red-boxed sub-matrices. I define
S = [1 4;
2 5]
that are the linear indices of the above matrices. So, A(S), B(S) and C(S) can extract the entries of the three matrices.
I pack them into vector by V = [ A(S)(:); B(S)(:); C(S)(:) ]. Let says after some manipulations, I obtain a new vector
V_new = [12 9 8 12 21 8 7 5 3 12 11 10]'
Here comes to my problem:
E.g for matrix A, I want to obtain
2->12, 5->9, 4->8 and 6->12
which are the first four entries of my V_new.
Since I have around 200 matrices, I have no idea to swap along the 200 matrices and the updated vector, V_new at the same time. Is writing a for-loop best way to do this purpose?
Thanks in advance.
Assuming that your A, B and C matrices have the same dimensions, rather work with a 3D matrix.
e.g. assuming your example matrices
M = cat(3,A,B,C)
No to extract those 4 upper left elements:
M_subset = M(1:2,1:2,:)
And then to reshape them into the vector you had:
V = M_subset(:)
then manipulate it to get V_new and finally put it back in the original:
M(1:2,1:2,:) = reshape(V_new,2,2,[])

Calculation the elements of different sized matrix in Matlab

Can anybody help me to find out the method to calculate the elements of different sized matrix in Matlab ?
Let say that I have 2 matrices with numbers.
Example:
A=[1 2 3;
4 5 6;
7 8 9]
B=[10 20 30;
40 50 60]
At first,we need to find maximum number in each column.
In this case, Ans=[40 50 60].
And then,we need to find ****coefficient** (k).
Coefficient(k) is equal to 1 divided by quantity of column of matrix A.
In this case, **coefficient (k)=1/3=0.33.
I wanna create matrix C filling with calculation.
Example in MS Excel.
H4 = ABS((C2-C6)/C9)*0.33+ABS((D2-D6)/D9)*0.33+ABS((E2-E6)/E9)*0.33
I4 = ABS((C3-C6)/C9)*0.33+ABS((D3-D6)/D9)*0.33+ABS((E3-E6)/E9)*0.33
J4 = ABS((C4-C6)/C9)*0.33+ABS((D4-D6)/D9)*0.33+ABS((E4-E6)/E9)*0.33
And then (Like above)
H5 = ABS((C2-C7)/C9)*0.33+ABS((D2-D7)/D9)*0.33+ABS((E2-E7)/E9)*0.33
I5 = ABS((C3-C7)/C9)*0.33+ABS((D3-D7)/D9)*0.33+ABS((E3-E7)/E9)*0.33
J5 = ABS((C4-C7)/C9)*0.33+ABS((D4-D7)/D9)*0.33+ABS((E4-E7)/E9)*0.33
C =
0.34 =|(1-10)|/40*0.33+|(2-20)|/50*0.33+|(3-30)|/60*0.33
0.28 =|(4-10)|/40*0.33+|(5-20)|/50*0.33+|(6-30)|/60*0.33
0.22 =|(7-10)|/40*0.33+|(8-20)|/50*0.33+|(9-30)|/60*0.33
0.95 =|(1-40)|/40*0.33+|(2-50)|/50*0.33+|(3-60)|/60*0.33
0.89 =|(4-40)|/40*0.33+|(5-50)|/50*0.33+|(6-60)|/60*0.33
0.83 =|(7-40)|/40*0.33+|(8-50)|/50*0.33+|(9-60)|/60*0.33
Actually A is a 15x4 matrix and B is a 5x4 matrix.
Perhaps,the matrices dimensions are more than this matrices (variables).
How can i write this in Matlab?
Thanks you!
You can do it like so. Let's assume that A and B are defined as you did before:
A = vec2mat(1:9, 3)
B = vec2mat(10:10:60, 3)
A =
1 2 3
4 5 6
7 8 9
B =
10 20 30
40 50 60
vec2mat will transform a vector into a matrix. You simply specify how many columns you want, and it will automatically determine the right amount of rows to transform the vector into a correctly shaped matrix (thanks #LuisMendo!). Let's also define more things based on your post:
maxCol = max(B); %// Finds maximum of each column in B
coefK = 1 / size(A,2); %// 1 divided by number of columns in A
I am going to assuming that coefK is multiplied by every element in A. You would thus compute your desired matrix as so:
cellMat = arrayfun(#(x) sum(coefK*(bsxfun(#rdivide, ...
abs(bsxfun(#minus, A, B(x,:))), maxCol)), 2), 1:size(B,1), ...
'UniformOutput', false);
outputMatrix = cell2mat(cellMat).'
You thus get:
outputMatrix =
0.3450 0.2833 0.2217
0.9617 0.9000 0.8383
Seems like a bit much to chew right? Let's go through this slowly.
Let's start with the bsxfun(#minus, A, B(x,:)) call. What we are doing is taking the A matrix and subtracting with a particular row in B called x. In our case, x is either 1 or 2. This is equal to the number of rows we have in B. What is cool about bsxfun is that this will subtract every row in A by this row called by B(x,:).
Next, what we need to do is divide every single number in this result by the corresponding columns found in our maximum column, defined as maxCol. As such, we will call another bsxfun that will divide every element in the matrix outputted in the first step by their corresponding column elements in maxCol.
Once we do this, we weight all of the values of each row by coefK (or actually every value in the matrix). In our case, this is 1/3.
After, we then sum over all of the columns to give us our corresponding elements for each column of the output matrix for row x.
As we wish to do this for all of the rows, going from 1, 2, 3, ... up to as many rows as we have in B, we apply arrayfun that will substitute values of x going from 1, 2, 3... up to as many rows in B. For each value of x, we will get a numCol x 1 vector where numCol is the total number of columns shared by A and B. This code will only work if A and B share the same number of columns. I have not placed any error checking here. In this case, we have 3 columns shared between both matrices. We need to use UniformOutput and we set this to false because the output of arrayfun is not a single number, but a vector.
After we do this, this returns each row of the output matrix in a cell array. We need to use cell2mat to transform these cell array elements into a single matrix.
You'll notice that this is the result we want, but it is transposed due to summing along the columns in the second step. As such, simply transpose the result and we get our final answer.
Good luck!
Dedication
This post is dedicated to Luis Mendo and Divakar - The bsxfun masters.
Assuming by maximum number in each column, you mean columnwise maximum after vertically concatenating A and B, you can try this one-liner -
sum(abs(bsxfun(#rdivide,bsxfun(#minus,permute(A,[3 1 2]),permute(B,[1 3 2])),permute(max(vertcat(A,B)),[1 3 2]))),3)./size(A,2)
Output -
ans =
0.3450 0.2833 0.2217
0.9617 0.9000 0.8383
If by maximum number in each column, you mean columnwise maximum of B, you can try -
sum(abs(bsxfun(#rdivide,bsxfun(#minus,permute(A,[3 1 2]),permute(B,[1 3 2])),permute(max(B),[1 3 2]))),3)./size(A,2)
The output for this case stays the same as the previous case, owing to the values of A and B.

Make vectors of unequal length equal in length by reducing the size of the largest ones

I am reading 5 columns from a .txt file to 5 vectors.
Sometimes some vectors are one element larger than others, so I need to check if they are all of equal length, and if not, I have to find which ones are the largest and delete their last element. I think I should be able to do this without loops. I was originally thinking of using find in combination with isequal but isequal only returns a logical, and does not provide any information on which vectors are the largest.
[Seconds,Sensor1VStatic,Sensor2VPulsed,TemperatureC,RelativeHumidity] = importfile(path);
Then depending on what vectors are longer by one element, I will do, for example
Seconds(end) = [];
Sensor1VStatic(end) = [];
If Seconds and Sensor1VStatic are longer than the other vectors by one element
Assume your vectors are in a cell array A:
A = {[1 2 3], [1 2 3 4], [1 2 3 4 5]};
You can get the size of each vector with
sz = cellfun(#(x)size(x,2), A);
Which will return (for the above example)
sz = [ 3 4 5]
Now you can find the shortest vector:
minLength = min(sz);
And finally, make all vectors this length:
B = cell2mat(cellfun(#(x)x(1:minLength), A, 'uniformoutput', false))';
There may be more elegant ways (and note that cellfun really is doing "implicit looping")
Applying this to your (now expanded) example, you could probably assign the output of importfile directly to the cell array - or you can do it as a separate line:
A = {Seconds,Sensor1VStatic,Sensor2VPulsed,TemperatureC,RelativeHumidity};
But it all becomes a lot of work. Instead you could do:
minLength = min(size(Seconds,1), size(Sensor1VStatic,1), size(Sensor2VPulsed,1), ...
Seconds = Seconds(1:minLength);
...
There is scope for some cleverness but it won't make things more readable, and it won't save time in the long run...

How to iterate over a changing vector in Matlab, not consecutive number?

I am really a beginner level at matlab. Now I want to have a loop, such that it iterates over a vector (not consecutive numbers) which contains a decreasing number of elements through iteration.
For example, I have [1; 2 ;3; 4] (thinking of it as person 1, 2, 3, 4)
then I want to do something such that for example person 1 and 4 gets food, person 2 and 3 left with no food.
In the next round, I want person 2 and 3 (those unassigned)to go through the assignment process again but not 1 and 4.
So I create a vector [2;3] to keep track of those left without food.
However,the for i=1:length(vector) gives me a series of consecutive numbers, what I want is
for i in vector do something; end
How to implement this?
when I just put
i=vector,
Matlab says Index exceeds matrix dimensions
If you want to loop through an arbitrary vector, just use that vector directly in a for loop. For example:
vector = [3, 4, 7, 1, 1]
for i = vector
disp(i)
end
will output 3 4 7 1 1. This is the equivalent of "for i in vector do something."
for i=1:length(vector) is giving you an index into the vector - it will always be consecutive because it represents the first..last position of the vector.
It sounds like you want to get an identifier out of the vector. You can do this within your existing loop: id=vector[i]
Have you thought about using Matlab structs?
s = struct(field1,value1,...,fieldN,valueN)
You can have an array 'people' of structs (of type person) which you can loop through...
for i=1:length(people)
if people(i).HasBeenFeed = False
% feed this person...
end
end