How to merge two 4D matrices? - matlab

I plan to merge two matrix using matlab.
A is M*N*3*P and B is M*N*3*Q.
how to get a matrix, which is M*N*3* (P+Q)?
Is there a function available?

The function you are looking for is called cat - "Concatenate arrays along specified dimension".
C = cat(dim, A, B) concatenates the arrays A and B along array
the dimension specified by dim. The dim argument must be a real,
positive, integer value.
In your case C = cat(4, A, B) does the trick. The dim=4 as A and B are both 4-dimensional and you want to concatenate in the 4th dimension.
Example:
A = ones(4,5,3,7);
B = zeros(4,5,3,17);
C = cat(4, A, B);
>> size(A)
ans =
4 5 3 7
>> size(B)
ans =
4 5 3 17
>> size(C)
ans =
4 5 3 24

Related

setdiff row by row without using loops in matlab

Let's say we have two matrices
A = [1,2,3;
2,4,5;
8,3,5]
B= [2,3;
4,5;
8,5]
How do I perform sediff for each row in A and B respectively without using loops or cellfun, in other words performing setdiff(A(i,:),B(i,:)) for all i. For this example I want to get
[1;
2;
3]
I am trying to do this for two very big matrices for my fluid simulator, thus I can't compromise on performance.
UPDATE:
you can assume that the second dimension (number of columns) of the answer will be fixed e.g. the answer will always be some n by m matrix and not some ragged array of different column sizes.
Another Example:
In my case A and B are m by 3 and m by 2 respectively and the answer should be m by 1. A solution for this case will suffice, but a general solution for matrices of size m by n1, m by n2 with answer of m by n3 will be very interesting. another example is
A = [1,2,3,4,5;
8,4,7,9,6]
B = [2,3;
4,9]
And the answer is
C = [1,4,5;
8,7,6]
Approach #1 Using bsxfun -
mask = all(bsxfun(#ne,A,permute(B,[1 3 2])),3);
At = A.'; %//'
out = reshape(At(mask.'),[],size(A,1)).'
Sample run -
>> A
A =
1 2 3 4 5
8 4 7 9 6
>> B
B =
2 3
4 9
>> mask = all(bsxfun(#ne,A,permute(B,[1 3 2])),3);
>> At = A.'; %//'
>> out = reshape(At(mask.'),[],size(A,1)).'
out =
1 4 5
8 7 6
Approach #2 Using diff and sort -
sAB = sort([A B],2)
dsAB = diff(sAB,[],2)~=0
mask1 = [true(size(A,1),1) dsAB]
mask2 = [dsAB true(size(A,1),1)]
mask = mask1 & mask2
sABt = sAB.'
out = reshape(sABt(mask.'),[],size(A,1)).'

Changing the size of a matrix in MATLAB

I am given the following matrices A of size 3x1 and B of size 5x1
A = B=
1 A
2 B
3 C
D
E
I want to convert matrix C in a 15x2 matrix
C =
1 A
1 B
1 C
1 D
1 E
2 A
.
.
.
3 E
How can I make it?
Can be done with repmat
D = repmat(A',size(B,1),1);
C = [D(:),repmat(B,size(A,1),1)]
Here's a different alternative based on code for generating truth tables from Generate All Possible combinations of a Matrix in Matlab
ind = dec2base(0:power(5,2)-1,5)-47;
C = [A(ind(1:15,1) + 48, B(ind(1:15,2)];
And if you want to generalize it
m = max(size(A,1),size(B,1));
n = size(A,1)*size(B,1);
col = 2;
ind = dec2base(0:power(n,col)-1,n)-47;
ind = ind(1:n,:);
C = [A(ind(:,1) + 48, B(ind(:,2)];
The + 48 is just to convert your A matrix from a numerical matrix to a char matrix so that C can hold both number and letters. You can leave it out if A was already a char matrix.
What's useful about this technique is that by changing col, this generalizes to combing more than just 2 vectors in a similar fashion

Find part of vector in another vector matlab

I would like to know if there is an easy way to find the indices of a vector in another vector in matlab:
a = [1 2 3 5 7 10 2 3 6 8 7 5 2 4 7 2 3]
b = [2 3]
So how to get the indices of a when comparing it with b (index of first element is needed)
In this case:
ans = [2 7 16]
Thanks in advance
find(a(1:end-1) == b(1) & a(2:end) == b(2) == 1)
You can re-purpose strfind by converting the elements of both vectors to byte arrays (uint8) with typecast:
bytesPerEl = numel(typecast(a(1),'uint8'));
byteLocs = strfind(char(typecast(a,'uint8')),char(typecast(b,'uint8')));
locsb = (byteLocs-1)/bytesPerEl + 1
locsb =
2 7 16
Just make sure a and b are of the same type. Also note that this works for 1D vectors, not matrixes or higher dimensional arrays.
General approach with length of b arbitrary (not necessarily 2 as in the example), and avoiding the use of strings:
match1 = bsxfun(#eq, a(:), b(:).'); %'// now we just need to make the diagonals
%// horizontal (in order to apply "all" row-wise). For that we'll use indices
%// ind, ind1, ind2
ind = reshape(1:numel(match1), numel(a), numel(b));
ind1 = nonzeros(tril(ind)); %// source indices
ind2 = sort(nonzeros(tril(flipud(ind)))); %// destination indices
match2 = zeros(size(match1));
match2(ind2) = match1(ind1); %// diagonals have become horizontal
result = find(all(match2.'));

MATLAB concatenate 2D matrix tiles

I have n2 equally sized (8x8) matrices which I want to tile into a single matrix like in the following diagram:
I know I could concatenate them column by column and then concatenate each row, but I want to know if there's a simpler method to achieve this.
There's a simpler method, you can store all your matrices in a cell array, then reshape and convert back to a matrix:
In the following example, suppose that C is your n2×1 cell array of matrices:
cell2mat(reshape(C, sqrt(numel(C)), []));
The result is a single tiled matrix A as required.
Example
a = ones(2); b = 2 * a; c = 3 * a; d = 4 * a;
C = {a, b, c, d};
A = cell2mat(reshape(C, sqrt(numel(C)), []))
The result is:
A =
1 1 3 3
1 1 3 3
2 2 4 4
2 2 4 4
Note the order of the sub-matrices: they are arranged column-wise. If you want A to be:
A =
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
then you'll have to pass the transposed version of C to reshape:
cell2mat(reshape(C', sqrt(numel(C)), []))
If you already have a for loop where you create the 8-by-8 matrices, you can do something like this:
M = 8; % Rows of each block matrix
N = 8; % Columns of each square block matrix
m = 2; % Number of blocks across
n = 2; % Number of blocks vertically
A(m*n*M,N) = 0; % Preallocate an m*n*M-by-N column of blocks
for i = 1:m*n
a = rand(M,N); % Create your data, just random here
A(1+M*(i-1):M*i,:) = a; % Insert data
end
A = reshape(A,[M*m N*n]); % Reshape to obtain block matrix
This assumes that you have a single for loop iterating over all n^2 (or m*n) cases. Also, it builds up A one column of blocks at a time. Note: if you need to build it with the blocks going across the rows first, then you'll need to change the allocation of A and how the data is inserted by swapping the indices.
Yes there is!
%Assuming your matrices are A1, A2, A3 and A4:
A = zeros(size(A1)*2);
A(1:8,1:8) = A1;
A(9:16, 1:8) = A2;
A(1:8, 9:16) = A3;
A(9:16, 9:16) = A4;

How to get a linear array when indexing 3rd or higher dimensions in multidimensional arrays

Consider having the following multidimensional array:
A = [1 2;3 4];
B = [5 6;7 8];
C = cat(3, A, B);
Well it is like a cube, I want to slice the first row, slice the first column and that's it.
When I do:
C(1,1,:)
I get two separate answers:
C(1,1,1) = 1
C(1,1,2) = 5
And if I do
D = C(1,1,:)
I get D to be a multidimensional.
I want this
D = [1 5];
That's it, how to do this?
Use the squeeze() function to drop the extra dimensions:
>> squeeze(C(1,1,:))'
ans =
1 5