Fast way of concatenating complex data using vertcat with custom rows - matlab

I need to concatenate few bigger matrices, but in specific manner - for example to concatenate only 1 row from X matrices.
There is a good solution of storing the data in a structure, so then there is no need of preparing long list of things that needs to be concatenated.
For example, we will have a structure like that:
struct(1).huge = [1 2 3 4; 1 2 3 4];
struct(2).huge = [1 2 3 4; 1 2 3 4];
struct(3).huge = [1 2 3 4; 1 2 3 4];
Then we can concatenate these with:
concatVar.concat = vertcat(struct.huge);
Instead of, for example:
concatVar.concat = vertcat(struct(1), struct(2),(...),struct(100));
But what if I need to concatenate only specific rows from different fields in the structure, for example only 1 row:
concatVar.concat = vertcat(struct.huge(1,:));
Then this method will not work, with the error:
"Expected one output from a curly brace or dot indexing expression, but there were X results".
Is it even possible of doing something like that in a fast and reliable way with use of vertcat or horzcat?
Thanks for any advice!
BM

It seems hard to avoid a loop in this case. You can convert the struct's field into a cell and then use cellfun, which is essentially a loop.
Let your struct be defined as follows. Note that it's not advised to use function names or reserved words like struct as variable names.
s(1).huge = [1 2 3 4; 1 2 3 4];
s(2).huge = [1 2 3 4; 1 2 3 4];
s(3).huge = [1 2 3 4; 1 2 3 4];
Then:
result = cell2mat(cellfun(#(x) x(1,:), {s.huge}, 'uniformoutput', false).');

Related

how to add 3 matrices with one dimension same for all and other dimension different in matlab?

I have matrices A=2x2 B=2x4 C=2x2 I want result in a matrix D=2x16 for example
A=[1 3;
2 4]
B=[3 2 4 2;
4 3 6 3]
C=[4 5;
7 5]
D=[(1+3+4) (1+3+5) (1+2+4) (1+2+5) (1+4+4) (1+4+5) (1+2+4) (1+2+5) (3+3+4) (3+3+5) (3+2+4) (3+2+5) (3+4+4) (3+4+5) (3+2+4) (3+2+5);
(2+4+7) (2+4+5) (2+3+7) (2+3+5) (2+6+7) (2+6+5) (2+3+7) (2+3+5) (4+4+7) (4+4+5) (4+3+7) (4+3+5) (4+6+7) (4+6+5) (4+3+7) (4+3+5)]
means that row wise elements are added in resultant. I have a code in which A=2x1 but I can understand how to mold it according to A=2x2 the code is given below
[rows,col_B]=size(B);
[~,col_C]=size(C);
result=zeros(rows,col_B*col_C);
for i=1:col_B
for j=1:col_C
result(:,(i-1)*col_C+j)=A+B(:,i)+C(:,j);
end
end
can anybody tell me the syntax for the output RESULT in this code?
Try
D = kron(A,ones(1,size(B,2)*size(C,2)))+repmat(kron(B,ones(1,size(C,2))),1,size(A,2))+repmat(C,1,size(B,2)*size(A,2))
Explained: kron(Mat, ones(1,num2RepeatColumns)), repeats each column of the matrix, Mat. So "repeating" twice makes A = [1 2; 3 4] becomes A = [1 1 2 2; 3 3 4 4], see Matlab: repeat every column sequentially n times
repmat(Mat, 1, num2RepeatMatrix) copies the whole matrix, Mat and "pastes" it right next to the original, so A=[1 2; 3 4] becomes A = [1 2 1 2; 3 4 3 4]. See "Horizontal Stack" example of repmat: https://www.mathworks.com/help/matlab/ref/repmat.html
OLD
D=[];
for ii=1:size(A,2)
D=[D,A(:,ii)+kron(B,ones(1,size(C,2)))+repmat(C,1,size(B,2))];
end

Can I get 2 set of random number array in matlab?

idx=randperm(5)
idx=[1,3,4,2,5]
I know this works like that but I'm curious about is there anyway to get something like this.
idx=[1,3,4,2,5,5,3,2,4,1]
adding one set of array after one array
Is there any way to make that?
One vectorized way would be to create a random array of size (m,n), sort it along each row and get the argsort indices. Each row of those indices would represent a group of randperm values. Here, m would be the number of groups needed and n being the number of elements in each group.
Thus, the implementation would look something like this -
[~,idx] = sort(rand(2,5),2);
out = reshape(idx.',1,[])
Sample run -
>> [~,idx] = sort(rand(2,5),2);
>> idx
idx =
5 1 3 2 4
4 3 2 5 1
>> out = reshape(idx.',1,[])
out =
5 1 3 2 4 4 3 2 5 1
You can use the modulo operation:
n = 5 %maximum value
r = 2 %each element are repeated r times.
res = mod(randperm(r*n),n)+1

How to get a unique array value in Matlab?

I have array value like this snippet below:
a = { [1 2 4]; [3 5 6 7]; [1 2 4]; [3 5 6 7]; [8 9]; []};
I am trying Matlab to get array value like this
a = { [1 2 4]; [3 5 6 7];[8 9]};
basic solution for finding uniques
unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
This can be found here actually.
Complicating factors
Technically the empty cell at the end is also unique, perhaps you want to remove it separately like so:
a(cellfun(#isempty,a)) = []
Currently you get strings as output, this can be solved like so:
[~, idx] = unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
a(idx)
I personally think that this is harder than it should be.
Summary
You can get your desired output like so
a(cellfun(#isempty,a)) = []
[~, idx] = unique(cellfun(#(x)(mat2str(x)),a,'uniformoutput',false))
a(idx)

Matrix power help/Matlab

I want to raise a matrix to a next matrix and subtrat one before taking the product.
e.g.
A = [2 3 5
2 3 0]
B = [2 2 1
1 2 0]
so prod(A.^B-1) would be:
first row (2^2-1)*(3^2-1)*(5^1-1)=96
second row (2^1-1)*(3^2-1)=8
and we would have prod(A.^B-1) = 96, 81. the trick also to skip past the zero, i keep getting zero or NaN, i think the zero is being calculated as well.
Is there a way to code this,
this is the code I have in mind
if A~=0 && B~=0
prod(A.^B-1)
end
You could do it like this using logical indexing to replace instances where A.^B-1 is 0:
A = [2 3 5;2 3 0];
B = [2 2 1;1 2 0];
C = A.^B-1;
C(C==0) = 1; % Replace zeros with ones
D = prod(C,2) % Product across the columns
which returns
D =
96
8
provided that you remove the zeros, I don't think that you should get NaN unless your original matrices contain it. However, You can replace it in the same manner as well (C(isnan(C)) = 1;).

splitting a Matrix into column vectors and storing it in an array

My question has two parts:
Split a given matrix into its columns
These columns should be stored into an array
eg,
A = [1 3 5
3 5 7
4 5 7
6 8 9]
Now, I know the solution to the first part:
the columns are obtained via
tempCol = A(:,iter), where iter = 1:end
Regarding the second part of the problem, I would like to have (something like this, maybe a different indexing into arraySplit array), but one full column of A should be stored at a single index in splitArray:
arraySplit(1) = A(:,1)
arraySplit(2) = A(:,2)
and so on...
for the example matrix A,
arraySplit(1) should give me [ 1 3 4 6 ]'
arraySplit(2) should give me [ 3 5 5 8 ]'
I am getting the following error, when i try to assign the column vector to my array.
In an assignment A(I) = B, the number of elements in B and I must be the same.
I am doing the allocation and access of arraySplit wrongly, please help me out ...
Really it sounds like A is alread what you want--I can't imagine a scenario where you gain anything by splitting them up. But if you do, then your best bet is likely a cell array, ie.
C = cell(1,3);
for i=1:3
C{i} = A(:,i);
end
Edit: See #EitanT's comment below for a more elegant way to do this. Also accessing the vector uses the same syntax as setting it, e.g. v = C{2}; will put the second column of A into v.
In a Matlab array, each element must have the same type. In most cases, that is a float type. An your example A(:, 1) is a 4 by 1 array. If you assign it to, say, B(:, 2) then B(:, 1) must also be a 4 by 1 array.
One common error that may be biting you is that a 4 by 1 array and a 1 by 4 array are not the same thing. One is a column vector and one is a row vector. Try transposing A(:, 1) to get a 1 by 4 row array.
You could try something like the following:
A = [1 3 5;
3 5 7;
4 5 7;
6 8 9]
arraySplit = zeros(4,1,3);
for i =1:3
arraySplit(:,:,i) = A(:,i);
end
and then call arraySplit(:,:,1) to get the first vector, but that seems to be an unnecessary step, since you can readily do that by accessing the exact same values as A(:,1).