I have a matrix for which I extract each column and do repmat function for each of them to build another matrix. Since i I have to do this for a large number of vectors(each column of my first matrix) it takes so long(relative to which I expect). If I do this for the whole matrix and then do something to build them, does it takes less time?
Consider this as an example:
A=[1 4 7;2 5 8;3 6 9]
I want to produce these
A1=[1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3]
A2=[4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6]
A3=[7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9]
As an alternative to #thewaywewalk's answer and using kron and repmat:
clear
A=[1 4 7;2 5 8;3 6 9];
B = repmat(kron(A',ones(3,1)),1,3);
A1 = B(1:3,:)
A2 = B(4:6,:)
A3 = B(7:end,:)
Which results in the following:
A1 =
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
A2 =
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
4 5 6 4 5 6 4 5 6
A3 =
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
7 8 9 7 8 9 7 8 9
Or as #Divakar pointed out, it would be advisable to create a single 3D array and store all your data in it (general solution):
n = 3; %// # of times you want to repeat the arrays.
A=[1 4 7;2 5 8;3 6 9];
B = repmat(kron(A',ones(n,1)),1,n);
C = zeros(n,n*size(A,2),3);
C(:,:,1) = B(1:n,:);
C(:,:,2) = B(n+1:2*n,:);
C(:,:,3) = B(2*n+1:end,:);
Try if this fits your needs:
A = [1 4 7;2 5 8;3 6 9];
n = 3; %// size(A,1)
cellArrayOutput = arrayfun(#(x) repmat( A(:,x).',n,n ), 1:size(A,2), 'uni',0)
instead of different variable names, everything is stored in a cell array.
if you insist on different names, I'd recommend to use structs:
A = [1 4 7;2 5 8;3 6 9];
n = 3;
structOutput = struct;
for ii = 1:size(A,2)
structOutput.(['A' num2str(ii)]) = repmat( A(:,ii).', n, n );
end
which gives you:
>> structOutput.A1
ans =
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
1 2 3 1 2 3 1 2 3
and so on.
I don't expect to much performance plus, you should share your full code for further help.
Related
This question already has answers here:
Matlab: repeat every column sequentially n times [duplicate]
(3 answers)
Closed 4 years ago.
Initial matrix is A = [ [1 2 3; 4 5 6; 7 8 9]. Every row is to be replicated 3 times such that the output matrix is
B = [1 2 3;1 2 3;1 2 3;4 5 6; 4 5 6; 4 5 6; 7 8 9; 7 8 9; 7 8 9]
B = replicate(permute(A,[3 2 1]),3,1)
you mean like that?
kron(A,ones(3,1))
ans =
1 2 3
1 2 3
1 2 3
4 5 6
4 5 6
4 5 6
7 8 9
7 8 9
7 8 9
Since R2015a, there is a dedicated function for this: repelem.
A = [1 2 3; 4 5 6; 7 8 9]
B = repelem(A,3,1)
B =
1 2 3
1 2 3
1 2 3
4 5 6
4 5 6
4 5 6
7 8 9
7 8 9
7 8 9
Or just indexing:
A = [1 2 3; 4 5 6; 7 8 9]; % original matrix
m = 3; % row repetition factor
n = 1; % column repetition factor
B = A(ceil(1/m:1/m:size(A,1)), ceil(1/n:1/n:size(A,2)));
for eg if i have a matrix
4 5 9 8 3 8
3 2 4 10 1 3
1 9 9 6 7 7
2 1 7 4 6 7
2 6 3 5 4 2
7 2 2 9 3 4
How do I calculate the sum of the diagonal of the element 10 if I have its row and column indices?
So the output should be 9 + 10 + 7 + 7.
Thanks!
column = 4;
row = 2;
output = sum(diag(A, column - row));
Here you go:
>> x = [4,5,9,8,3 ,8
3,2,4,10,1, 3
1,9,9,6,7 ,7
2,1,7,4,6 ,7
2,6,3,5,4 ,2
7,2,2,9,3 ,4]
x =
4 5 9 8 3 8
3 2 4 10 1 3
1 9 9 6 7 7
2 1 7 4 6 7
2 6 3 5 4 2
7 2 2 9 3 4
>> xsum = sum(diag(x,4-2));
>> xsum
xsum = 33
parameterize the indices in case you need to use it more than once.
I have a 3D matrix and I want to store each 2D component of this in the row of another 2D matrix which has many rows as the 3rd dimension of the 3D matrix.
How can I do this?
With permute & reshape -
reshape(permute(A,[3 2 1]),size(A,3),[])
Sample run -
>> A
A(:,:,1) =
7 1 7 5
3 4 8 5
9 4 2 6
A(:,:,2) =
7 7 2 4
7 6 5 6
3 2 9 3
A(:,:,3) =
7 7 5 3
3 9 2 8
5 9 2 3
>> reshape(permute(A,[3 2 1]),size(A,3),[])
ans =
7 1 7 5 3 4 8 5 9 4 2 6
7 7 2 4 7 6 5 6 3 2 9 3
7 7 5 3 3 9 2 8 5 9 2 3
If you don't mind a little indexing madness...
You can build a linear index with the appropriate shape, which applied on the original array will give the desired result:
B = A(bsxfun(#plus, (1:L*M:L*M*N).', reshape(bsxfun(#plus, (0:L:L*M-1).', 0:L-1),1,[])));
Example:
>> A = randi(10,2,3,4)-1; %// example array; size 2x3x4
>> A
A(:,:,1) =
5 3 2
9 8 9
A(:,:,2) =
8 7 4
9 8 6
A(:,:,3) =
3 4 8
0 4 4
A(:,:,4) =
2 8 8
4 6 7
Result:
>> B
B =
5 3 2 9 8 9
8 7 4 9 8 6
3 4 8 0 4 4
2 8 8 4 6 7
That is easily done with MATLABs matrix unrolling syntax:
A=ones(N,M,O);
B=zeros(O,N*M);
for ii=1:size(A,3)
aux=A(:,:,ii); % aux is NxM
B(ii,:)=aux(:); % unroll!
end
(note I called O the thing you call N in your pictures)
I would like to resize a matrix under the form let's say 4x3x5, to a 2d matrix of 20x3 but while preserving the order as illustrated below :
The function reshape() does not keep this particular order, how could I achieve this the simplest way possible ?
Let's solve these problems of concatenating and cutting across the third dimension once and for all!
Part I (3D to 2D) : Concatenate along the columns and across the 3rd dim of a 3D array, A to form a 2D array -
reshape(permute(A,[1 3 2]),[],size(A,2))
Part II (2D to 3D) : Cut a 2D array B after every N rows to form 3D slices of a 3D array -
permute(reshape(B,N,size(B,1)/N,[]),[1 3 2])
Sample run -
Part I (3D to 2D)
>> A
A(:,:,1) =
4 1 4 3
8 4 6 4
8 5 6 1
A(:,:,2) =
9 4 4 1
2 2 9 7
1 5 9 3
A(:,:,3) =
4 4 7 7
5 9 6 6
9 3 5 2
>> B = reshape(permute(A,[1 3 2]),[],size(A,2));
>> B
B =
4 1 4 3
8 4 6 4
8 5 6 1
9 4 4 1
2 2 9 7
1 5 9 3
4 4 7 7
5 9 6 6
9 3 5 2
Part II (2D to 3D)
>> N = 3;
>> permute(reshape(B,N,size(B,1)/N,[]),[1 3 2])
ans(:,:,1) =
4 1 4 3
8 4 6 4
8 5 6 1
ans(:,:,2) =
9 4 4 1
2 2 9 7
1 5 9 3
ans(:,:,3) =
4 4 7 7
5 9 6 6
9 3 5 2
I'm working on MATLAB. I have the following matrices
A = [
1 2 3 4
5 6 7 8
1 5 2 3
6 7 8 9
1 3 6 2
6 3 1 6
9 7 4 7
];
B = [
1 5 2 3
6 7 8 9
];
I want to find A-B
so that the answer should be like,
ans = [
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
];
Use setdiff with the 'rows' and 'stable' options:
>> C = setdiff(A,B,'rows','stable')
C =
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
Use ismember to find the common rows and neglect those in the final output.
Code
out = A(~ismember(A,B,'rows'),:)
Output
out =
1 2 3 4
5 6 7 8
1 3 6 2
6 3 1 6
9 7 4 7
clear;
s=0;
A = [
1 2 3 4
5 6 7 8
1 5 2 3
6 7 8 9
1 3 6 2
6 3 1 6
9 7 4 7
];
B = [
1 5 2 3
6 7 8 9
];
for i=1:size(B)
s=s+(ismember(A, B(i,:), 'rows'))
end
A_B = A(s==0,:)
#Divakar or #chappjc's answers are the way to go.
But I can't help inviting bsxfun to the party:
C = A(~any(squeeze(all(bsxfun(#eq, A.', permute(B, [2 3 1])))).'),:);
And its friend pdist2 is coming too:
C = A(all(pdist2(A, B, 'hamming').'),:);