MATLAB intersection of 3d arrays - arrays

I have two 3d arrays:
A(:,:,1) = [1 2 3; 4 5 6; 7 8 9];
A(:,:,2) = [1 0 0; 0 1 0; 0 0 1];
A(:,:,3) = [3 2 1; 6 5 4; 9 8 7];
...
and
B(:,:,1) = [1 1 1; 2 2 2; 3 3 3];
B(:,:,2) = [1 0 0; 0 1 0; 0 0 1];
B(:,:,3) = [3 3 3; 2 2 2; 1 1 1];
...
They both consist of 3x3 matrices and their third dimensions are very large. I want to obtain the array of matrices that exist in both arrays. I am doing it in a for loop by comparing element-wise (matrix-wise). It takes a very long time, so I am looking for an easier way (or an existing function) to do the same.
Thanks!

Collapse the first two dimensions into one and transpose, so that matrices of the 3D array become rows of a matrix. That way you can use intersect(...,'rows'). Finally, transpose back and reshape back:
[m, n, p] = size(A);
result = intersect(reshape(A, [], p).', reshape(B, [], p).', 'rows');
result = reshape(result.', m, n, []);

Related

How to reconstruct a 2D K-by-K square matrix from a 1D vector that contain its upper diagonal element given that the other element are zeros?

I got a vector of numbers with length 6 like this a = [1 2 3 4 5 6] and I want to reconstruct the corresponding 4-by-4 matrix A like this where all the element from the diagonal to the other lower diagonal are all zero.
A = [0 1 2 3
0 0 4 5
0 0 0 6
0 0 0 0]
The relationship between the vector a and the corresponding matrix A is that if the dimension of the matrix is K then the length of vector a is K(K-1)/2. In this case the length of a is 6 which mean K = 4.
Another example case would be a = [1 2 3] then
A = [0 1 2
0 0 3
0 0 0
How can I do this?
If you have the Statistics Toolbox, just use squareform and triu:
a = [1 2 3 4 5 6];
A = triu(squareform(a, 'tomatrix'));
Without the toolbox:
a = [1 2 3 4 5 6];
n = (1 + sqrt(1+8*numel(a)))/2; % size of matrix
A = zeros(n); % initiallize
A((1:n).'>(1:n)) = a; % build logical mask using implicit expansion, and fill the
% lower half of the matrix with the desired values in column-major order
A = A.'; % transpose to put the values into the upper half in row-major order

From vector to matrix reshape every ith rows for each column

I have this vector:
arr = [1; 2; 3; 1; 2; 3; 1; 2; 3; 1; 2; 3]
And would like to turn it into a 4x3 matrix looking like this:
mat = [1 1 1;...
2 2 2;...
3 3 3;...
1 1 1;...
2 2 2;...
3 3 3;...
1 1 1;...
2 2 2;...
3 3 3;...
1 1 1;...
2 2 2;...
3 3 3]
So far I achieved this by doing:
a1 = arr(1:3:end);
a2 = arr(2:3:end);
a3 = arr(3:3:end);
mat = [a1 a2 a3];
Is there a more convenient way with for instance the reshape function?
reshape does not change the number of the elements in a matrix. It reshapes the matrix by rearranging the existing elements.
In your case, you can use repmat, which copies a matrix or vector one or multiple times:
mat = repmat(arr,1,3);
You can read more about repmat here.
Also, your solution does not give the matrix you showed in the code block. To get the result given by your solution, you can use reshape as such:
mat = reshape(arr,3,4)'

MATLAB: Permute and reshape a N x 4 array into a 2 x 2 x N array

I have a question that seems like it should have a simple answer that can avoid for loops.
Suppose I have an N x 4 array defined in MATLAB:
A = [1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4; 1 2 3 4];
In this example, N = 6, but it is arbitrary. I want to re-arrange A into a new array, B, which is 2 x 2 x N array of the form:
B(:,:,1) = [1 2; 3 4];
B(:,:,2) = [1 2; 3 4];
...
B(:,:,N) = [1 2; 3 4];
This seems like a simple problem and I tried a variety of things such as:
B = reshape(A',2,2,N);
However, this results in
B(:,:,1) = [1 3; 2 4];
B(:,:,2) = [1 3; 2 4];
...
B(:,:,N) = [1 3; 2 4];
I feel like there must be a simple way of doing this in one line using some combination of "reshape", "permute" and/or "transpose" that I am missing. Any suggestions are appreciated.
You are only missing a final permute. This is needed because Matlab is column-major, so it fills the new array down, then across:
B = permute(reshape(A.', 2,2,N), [2 1 3]);

Matlab: Assemble submatrices whose #cols and #rows are stored in a vector

I have two vectors, R and C, which have the number of rows and columns, respectively, of submatrices that I need to assemble in a ones matrix I (40x20). There's 12 submatrices total.
R = [4 2 4 4 2 4];
C = [4 16 16 4];
Moreover, all the elements of each submatrix have its value stored in vector k:
k = [3 2 3 3 2 3 2 1 2 2 1 2 2 1 2 2 1 2 3 2 3 3 2 3 ]; % 24 elements
Thus for instance, submatrix M(1:4,1:4) has 4 rows, and 4 columns and value equal to k(1) = 1.
QUESTION: How can I assemble matrix M with all submatrices?
Any ideas?
Thanks!
EDIT:
The matrix M should look like this:
and the submatrices:
and the values of k:
Here is a vectorized solution:
R1 = repelem(1:numel(R), R);
C1 = repelem(1:numel(C), C);
[CC RR] = meshgrid(C1, R1);
idx = sub2ind([numel(R), numel(C)], RR, CC);
result = k(idx);
Instead you can use cell array, fill it with sub matrices and then convert the cell array to a matrix.
carr = cell(numel(R), numel(C));
k1 = reshape(k,numel(R),numel(C));
for ii = 1:numel(R)
for jj = 1:numel(C)
carr(ii,jj)=repmat(K1(ii,jj), R(ii), C(jj));
end
end
result = cell2mat(carr)

Block diagonal matrix from columns

Suppose I have an m x n matrix A .
Is there a way to create B, a (n x m) x n matrix whose "diagonal" is formed by A's columns ?
Example:
A = [1 2;
3 4]
B = [1 0;
3 0;
0 2;
0 4]
Here is a way:
Convert A to a cell array of its columns, using mat2cell;
From that cell array generate a comma-separated list, and use it as an input to blkdiag.
Code:
A = [1 2; 3 4]; %// example data
C = mat2cell(A, size(A,1), ones(1,size(A,2))); %// step 1
B = blkdiag(C{:}); %// step 2
This produces
B =
1 0
3 0
0 2
0 4
Here is a short script to accomplish this. It works for any dimensions of A.
A=[1 2; 3 4];
[R C] = size(A);
for i=1:C
B( 1+R*(i-1) : R*i , i ) = A(:,i);
end

Resources