Create third matrix in MATLAB from combination of two other matrices - matlab

I have two expressions in MATLAB that represent a 365x24 matrix. The first expression has 10, 365x24 matrices and is therefore
PV_power_output(:,:,K)
and the second expression which is again 365x24 but with three possible matrices therefore is
WT_energy_supply(:,:,M);ode here
Now, I am looking to create a third matrix that adds the elements in the same position above and thus form a 365x24 matrix. However I want a set of matrix with all possible combinations of the two expressions shown above (therefore this matrix must be 365x24x30.
How do I go about this?
What about the bsxfun function in MATLAB?

Expand the original matrices (which for clarity I name a and b) with repmat and then just add them, bsxfun is not needed.
repmat(a,[1 1 size(b,3)]) + repmat(b,[1 1 size(a,3)]))
Update
>> size(a)
ans =
364 24 10
>> size(b)
ans =
364 24 3
>> c=repmat(a,[1 1 size(b,3)])+repmat(b,[1 1 size(a,3)]);
>> size(c)
ans =
364 24 30
It looks fine to me. Of course you'll have to replace my variables a and b with your variables PV_power_output and WT_energy_supply.

Related

How to store all columns of the matrix in Matlab workspace

Sorry for the vague title, but I wasn't sure how to name it properly.
Let's say I have this vector:
v=[2 5 8]';
Also I have the range of numbers as follow:
x=2:4
I want to create a for loop that will multiply the vector by 2, then use this newly created vector and multiply it by 3 and then use that and multiply it by 4. What I essentialy want is a 3 by 3 matrix
When I code something like this:
v=[2 5 8]';
for i= 2:4
k=v*i
end
This doesn't work because
a) Instead of multiplying by the next number in the loop it just adds the elements to itself i.e( in the second iteration I want (12, 30, 48)' and not (6,15,24)'
b) It doesn't store all 3 sets of values in the workspace.
EDIT
for i=1:1:length(x)
c1=fftshift(fft(u0z));
c2=exp(-1j*(p^2*x(i)/(2*lamda))).*c1;
c3=ifft(ifftshift(c2));
u1=exp(1j*lamda*(n(i)^2-1)*x(i)/2).*c3;
u0z=u1
end
Edit 2
for k=1:1:length(x)
c1=fftshift(fft(u0z));
c2=exp(-1j*(p^2*x(k)/(2*lamda))).*c1;
c3=ifft(ifftshift(c2));
u1=exp(1j*lamda*(n(k)^2-1)*x(i)/2).*c3;
u0z=u1;
mat(:,k)=u0z;
end
Using MATLAB's cumprod and implicit expansion (for MATLAB before R2016b, you need bsxfun for that), that's a one-liner:
v * cumprod(x)
% bsxfun(#times, v, cumprod(x))
ans =
4 12 48
10 30 120
16 48 192
Hope that helps!

Create vector from elements other than diagonal ones

I would like to create a column vector from the elements of a matrix A of size (3,3) that are not on the diagonal. Thus, I would have 6 elements in that output vector. How can I do this?
Use eye and logical negation, although this is no better than Divakar's original answer, and possibly significantly slower for very large matrices.
>> A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
>> A(~eye(size(A)))
ans =
5
9
4
2
7
14
3
10
15
13
8
12
Use this to get such a column vector, assuming A is the input matrix -
column_vector = A(eye(size(A))==0)
If you don't care about the order of the elements in the output, you can also use a combination of setdiff and diag -
column_vector = setdiff(A,diag(A))
You can also use linear indexing to access the diagonal elements and null them. This will automatically reshape itself to a single vector:
A(1:size(A,1)+1:end) = [];
Bear in mind that this will mutate the original matrix A. If you don't want this to happen, make a copy of your matrix then perform the above operation on that copy. In other words:
Acopy = A;
Acopy(1:size(A,1)+1:end) = [];
Acopy will contain the final result. You need to create a vector starting from 1 and going to the end in increments of the rows of the matrix A added with 1 due to the fact that linear indices are column-major, so the linear indices used to access a matrix progress down each row first for a particular column. size(A,1) will allow us to offset by each column and we add 1 each time to ensure we get the diagonal coefficient for each column in the matrix.
Assuming that the matrix is square,
v = A(mod(0:numel(A)-1, size(A,1)+1) > 0).';

Why does a column vector return a row vector when used to index matrices?

Imagine the following matrix is defined in MATLAB:
>> matrix=10:18
matrix =
10 11 12 13 14 15 16 17 18
Now I want to use another matrix to index the first one
>> index=[1,2;3,4]
index =
1 2
3 4
>> matrix(index)
ans =
10 11
12 13
So far so good, the size of the answer matches that of the matrix 'index'. If I use a row vector as the indexing matrix, the output is a row vector too. But the problem appears when I use a column vector as the indexing matrix:
>> index=(1:3)'
index =
1
2
3
>> matrix(index)
ans =
10 11 12
As you can see, here the size of the answer does not agree with the size of the matrix 'index'. This inconsistency in the sizes of the indexing matrix and the ans matrix prevents me from writing a piece of code accepting an indexing matrix of an arbitrary size.
I wonder if someone else has come across this problem before and has found some sort of solution to it; in other words, how can I force MATLAB to give me an ans matrix of the same size as the arbitrarily sized indexing matrix?
Cheers
Solution
#Dev-iL has nicely explained here why this is the way Matlab behaves, and #Dan has presented a general solution here. However, there was a simpler ad-hoc workaround for my code which I've explained here.
The reason comes from the function subsref.m, which is called when using parentheses:
%SUBSREF Subscripted reference.
% A(I) is an array formed from the elements of A specified by the
% subscript vector I. The resulting array is the same size as I except
% for the special case where A and I are both vectors. In this case,
% A(I) has the same number of elements as I but has the orientation of A.
As you can see, in the special case of vectors, the shape of the result will be the same as that of matrix in your example.
As for a workaround, IMHO Dan has the cleanest solution.
Preallocate the output matrix with the size of index matrix.
Then assign corresponding indices the corresponding values
out = zeros(size(index));
out(index) = matrix(index);
Example
index = (1:3)'
index =
1
2
3
>> out = zeros(size(index))
out =
0
0
0
>> in = magic(3)
in =
8 1 6
3 5 7
4 9 2
>> out(index) = in(index)
out =
8
3
4
>>
Dev-iL has explained why it is like that. Here is a potential workaround:
reshape(matrix(index),size(index))

Matlab column aggregation

Is there a function in MATLAB which allows to aggregate (or we can say sum) columns in a matrix per defined number of columns?
For example I have:
A =
1 2 3 4 5 6
9 10 11 12 13 14
17 18 19 20 21 22
I wish to aggregate every 2 columns, like this: col1+col2, and then col3+col4, and then col5+col6, so my output is:
A_agg =
3 7 11
19 23 27
35 39 43
I couldn't find a built-in function and was trying to write a for loop but I couldn't manage to do it since I am quite new to programming. Do you have any suggestions/solutions how this could be solved with a for loop, or maybe there is a built-in function?
Since sum operates down columns in a matrix, I first reshape A so that it has 2 rows and 9 columns, then sum down each column. Then reshape back to the desired output matrix A_agg.
A=[1 2 3 4 5 6
9 10 11 12 13 14
17 18 19 20 21 22]
[m,n]=size(A);
A_agg=reshape(sum(reshape(A',2,[])),m,[])'
You can use a combination of mat2cell and cellfun. You can use mat2cell to split up your matrices into individual 2 column chunks. Each chunk would be stored as a cell in a cell array. You can then use cellfun to take each cell and sum row-wise. After you're done, you can use cell2mat to convert back.
Using your example:
A = [1:6;9:14;17:22];
B = mat2cell(A, 3, [2 2 2]);
C = cellfun(#(x) sum(x,2), B, 'UniformOutput', false);
A_agg = cell2mat(C);
A_agg should thus give you:
A_agg =
3 7 11
19 23 27
35 39 43
Let's walk through the code slowly:
A is defined as we had before. B will be a cell array, and will segment your matrix into matrices of 2 columns per cell. The first parameter is the matrix you want to decompose (in our case A). The second parameter tells you how many rows each segment should have. Because we want all of the matrices to have the same number of rows, we thus supply one number which is 3. After, you specify the number of columns you want per matrix. Because there are 6 columns, we need 3 matrices, and so you'd specify a vector of [2 2 2].
C is the output of cellfun, where cellfun applies a function to every single element in a cell matrix. What you want to do here is for each cell (essentially each matrix), you want to sum row-wise. The first parameter is an anonymous function that takes in a matrix from each cell, and sums row-wise. The second parameter is the cell array we just created. You'll notice that we have an additional flag to set: UniformOutput. The reason why you have to set UniformOutput = false is because if you apply cellfun without that flag, the expected result at the end of the function you apply to each cell is scalar. Because we are outputting a column vector instead, we have to set this flag to false.
A_agg will thus aggregate all of your cells back to matrix form.
If you want to do this for any size matrix, bear in mind that there has to be an even amount of columns for this work. What I mean by even is that the number of columns has to be evenly divisible by 2. You would thus re-run the code like so:
B = mat2cell(A, size(A,1), 2*ones(1, size(A,2)/2));
C = cellfun(#(x) sum(x,2), B, 'UniformOutput', false);
A_agg = cell2mat(C);
Another possibility, if you have the Image Processing Toolbox, is to use blockproc. Let n denote the number of columns to be aggregated (2 in your example). Then:
A_agg = blockproc(A, [size(A,1) n], #(x) sum(x.data, 2));

Doing operations between subsequent elements without using a FOR loop?

In Matlab, Is it possible to do simple operations between subsequent elements of an array without using a for loop? Something like diff(). For example, I have this vector:
A = [2 4 8 16 32]
and I want each element to be divided by its predecessor:
ans = [2 2 2 2]
How can I do it without going through all elements (without using loops)?
You can use the fact that division in Matlab work on both scalars and matrices, if you use the ./ operator rather than /
>> A = [2 4 8 16 32];
>> A(2:end) ./ A(1:end-1)
ans =
2 2 2 2
Regarding your question about doing dot() between vectors stored in the rows of a matrix. There is an additional argument to dot() that tells it whether your vectors are stored in columns (the default) or rows;
>> x = rand(3);
>> y = rand(3); # random vectors
>> dot(x,y) # dot product of column vectors
ans =
0.5504 0.5561 0.5615
>> dot(x,y,2) # dot product of row vectors
ans =
0.3170
1.0938
0.2572
Most functions in Matlab are vectorized so that they can work on scalars, vectors and matrices, but you sometimes have the read the documentation (e.g. type help dot) to work out how to use them.