matlab - how to merge/interlace 2 matrices? - matlab

How can I combine 2 matrices A, B into one so that the new matrix C = row 1 of A, followed by row 1 of B, then row 2 of A, row 2 of B, row 3 of A, row 3 of B, etc? Preferably without a for loop?
ex: A = [1 2 3; 4 5 6], B = [5 5 5; 8 8 8].
AB = [1 2 3; 5 5 5; 4 5 6; 8 8 8].

All you need is a bit of catenation and reshaping. First, you catenate along dimension 2, then you transpose, and linearize (AB(:)), so that you get a vector whose first three elements are the first row of A, then the first row of B, then the second row of A, etc. All that's left in the end is calling reshape to put everything back into an array again.
nColumns = size(A,2);
AB = [A,B]';
AB = reshape(AB(:),nColumns,[])';
Alternatively, you can construct AB directly via indexing. In this case, A is allowed to have one more row than B. This is probably faster than the above.
[nRowsA,nCols] = size(A);
nRowsB = size(B,1);
AB = zeros(nRowsA+nRowsB,nCols);
AB(1:2:end,:) = A;
AB(2:2:end,:) = B;

Related

program to choose 4 columns from 5 column matrix and find determinant in MATLAB

How can I make a program in MATLAB that will choose 4 columns out of a 5 column matrix and find the determinant from that new 4x4 matrix?
I tried setting each column as a vector with a variable:
a = [1; 2; 3; 4];
b = [5; 6; 7; 8]
c = [9; 0; 1; 2];
d = [3; 4; 5; 6];
e = [7; 8; 9; 0];
I need to make the program choose four out of the five vectors (in any order) and find the determinant.
Any help at all will be appreciated, thanks.
To control which columns the determinant is applied on, combine the columns into a single matrix, then choose the columns using indexing via cols
M = [a b c d e];
cols = [1 3 4 5];
det(M(:,cols))

How to distinguish the two picture matrices?

I have a picture matrix A, the size of which is 200*3000 double. And I have another picture matrix B, the size of which is 200*1000 double. The 1000 columns of matrix B exactly comes from the columns of matrix A. My question is:
How to get a matrix C with the same size of matrix A, but only keep the original values of columns in matrix B? I mean the size of matrix C is 200*3000 double, but only 1000 columns have the same values as matrix B. The other 2000 columns will be set to another value d, that is my second question, what is the value I should set for d, so that the picture matrix C can distinguish from picture matrix A?
Use ismember with the 'rows' option. Here's an example:
A = [1 2 3 4; 5 6 7 8]; %// example A
B = [3 10 1; 7 20 5]; %// example B
val = NaN; %// example value to indicate no match
C = A; %// initiallize
ind = ismember(A.',B.','rows'); %// matching columns
C(:,~ind) = val; %// set non-matching columns to val
Equivalently, you coud replace ismember by bsxfun, so that line becomes
ind = any(all(bsxfun(#eq, A, permute(B, [1 3 2])), 1), 3);
In this example,
A =
1 2 3 4
5 6 7 8
B =
3 10 1
7 20 5
C =
1 NaN 3 NaN
5 NaN 7 NaN

Using find function

Consider the following arrays:
A = [1 3 4 5 6 7 1 3 7];
B = [1 4 7];
I want to find all elements of B in array A. So, my final output array will look something like:
C = [1 7 3 6 9];
First element of B is at locations 1 and 7 in array A, so C has 1 and 7 as first two elements. Element 4 of B is at location 3, so array C has 3 as its third element and so on.
The order of C is required?
Fast, but another order:
find(ismember(A,B))
Slower, but the order you want:
cell2mat(arrayfun(#(x)(find(A==x)),B,'UniformOutput',false))
Basically, the second solution iterates over all elements of B and applies find(A==x) in a loop.
You may also delete the cell2mat, then a cell is returned. First element -> Occurrences of 1, second element-> occurrences of 4 etc.
If you need the result in that order: you can use the two outputs of ismember. This may be faster than Daniel's answer (second part) as it avoids arrayfun:
[tf, loc] = ismember(A,B);
loc = loc(tf);
ind = find(tf);
[~, order] = sort(loc);
C = ind(order);
Second output of ismember will give a map for each element of B
>> [~,ic] = ismember(A,B)
ic =
1 0 2 0 0 3 1 0 3
Then element-wise test against each element of B:
>> [C,~] = find(bsxfun(#eq,ic.',1:numel(B)))
C =
1
7
3
6
9
And because I'm require to do so, an alternative method following ismember:
c = accumarray(nonzeros(ic),find(ic),[],#(x) {sort(x)});
C = vertcat(c{:})

Construct a matrix from existing two other matrices, all with different sizes

I have two matrices
a = randi ([0 10], 5, 6)
b = randi ([0 10], 2, 45)
Now I want to construct a matrix c of size 8 x 15 with all the elements of a and b. Is it possible to do it in a single line code? Some suggestions please.
Here is an example of what I'm trying to do:
a = [1 4 6;
5 8 0;
3 7 9;
4 10 5];
b = [5 6;
5 0];
c = [1 4 6 5;
8 0 3 7;
9 4 10 5;
5 6 5 0]
The specifications for how to combine a and b aren't clear. Here is one way to do it.
Create a single column vector built from a and b. Then reshape that column vector into a matrix.
c = reshape( [ a(:); b(:) ], 8, 15);
This will only work if the numel(a) + numel(b) equals the total number of elements in c.
Attempts to execute c = reshape( [ a(:); b(:) ], 7,12); will fail as you aren't providing enough elements to create an 7x12 matrix.
Update
Noufal's comment on this answer changes the problem reqs a bit. Basically you stil create the column vector but you only populate C depending on how many elements you have at your disposal:
A = rand(5,6);
B = rand(2,45);
C = zeros(8,10);
tmp = [A(:); B(:)]; % create temporary column vector
maxIdx = min( [numel(tmp), numel(C)] ); % determine if tmp or C has fewer elements
C(1:maxIdx) = tmp(1:maxIdx); % fill C from tmp using indices 1:maxIdx

Compare two unequal matrix some specific column without using for loop

I want to compare two matrices without using a for loop. Given
A=[2 1 8;
2 4 7;
2 3 7;
3 5 2;
5 1 4;
5 6 2;
5 3 7];
B=[3 6 5;
1 4 2];
Now I want to compare col(2) two of matrix B with col(2) two of matrix A and at the same time col(3) three of matrix B and col(1) one of matrix A. Now I want to get the result from matrix A like this:
c=[2 4 7;
5 6 2];
I think #mizanbuet wants to extract rows from A where the 3rd element of the row is in the first column of B and the 2nd element in the row is in the 2nd column of B.
Easy with some ismember and logical indexing:
A2inB2 = ismember(A(:,2),B(:,2));
A1inB3 = ismember(A(:,1),B(:,3));
c = A( A2inB2 & A1inB3, :);