Copy to and delete from matrices - matlab

Not sure even if this question stands valid. But better ask.
Suppose we have two matrices in MATLAB of size (n,1) and (m,1) and we want to copy certain rows from matrix A to matrix B on a condition.
e.g. if value A(i,1) is less or equal to X
And later delete those rows from source matrix i.e. matrix A
Example:
A = [1, 2, 3, 4, 5, 6]
B = [8, 9]
copy all values which are less than or equal to 4 from A to B, and delete from A
Matrices becomes
A = [5, 6]
B = [8, 9, 1, 2, 3, 4]

You can use a logical matrix to identify the items:
mask = (A <= 4);
B = [B A(mask)];
A(mask) = [];

Related

Octave/MATLAB: Using a matrix to access elements in a matrix without loops

Consider, the two matrices:
>> columns = [1,3,2,4]
and
>> WhichSet =
[2, 2, 1, 2;
1, 1, 2, 1;
1, 2, 1, 2;
2, 1, 2, 2]
My intent is to do the following:
>> result = [WhichSet(1,columns(1)), WhichSet(2,columns(2)), WhichSet(3, columns(3)) and WhichSet(4, columns(4))]
result = [2,2,2,2]
without any loops.
Because how indexing works, you can not just plug them as they are now, unless you use linear indexing
Your desired linear indices are:
ind=sub2ind(size(WhichSet),1:size(whichSet,1),columns);
Then
out=WhichSet(ind);

MATLAB replacing certain values of matrix with another matrix

I have an arbitrary matrix, a = [1, 0, 0, 1].
I want to replace every 0 value with the values of another matrix b = [1, 2, 3], and every 1 value with the value of yet another matrix c = [3, 4, 5].
I would therefore end up with the matrix [3, 4, 5, 1, 2, 3, 1, 2, 3, 3, 4, 5].
I've tried finding the indices of the 0 and 1 values and replacing the values at those indices with b and c, but this isn't allowed since they aren't the same size. Is there any simple way of achieving this?
Given
a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];
Let's first take the arrays we want in the final matrix and put them in a cell array:
parts = {b, c}
parts =
{
[1,1] =
1 2 3
[1,2] =
3 4 5
}
The goal is to use the values of a as indices into parts, but to do that we need all of the values to be positive from 1 to some n (if there are missing values it'll take a bit more work). In this case we can just increment a:
a_inds = a + 1
a_inds =
2 1 1 2
Now we can get a new cell array by doing parts(a_inds), or a matrix by adding cell2mat:
result = cell2mat(parts(a_inds))
result =
3 4 5 1 2 3 1 2 3 3 4 5
This can also be done with a key:value map.
a = [1, 0, 0, 1];
b = [1, 2, 3];
c = [3, 4, 5];
keyset = [1,0];
valueset = {b,c};
mapobj = containers.Map(keyset,valueset);
new_vec = [];
for i =1:length(a)
new_vec(length(new_vec)+1:length(new_vec)+length(mapobj(a(i))))= mapobj(a(i));
end
1 is mapped to b and 0 mapped to c. The for loop iterates over a building an ever longer vector containing the mapped values.
This code will allow for non-sequential keys such that 37 could be added and mapped to another vector, whereas in the previous answer you would have to map 2 to the next vector in order for the code not to break.

How to extract values from a Matrix that recorded in a vector?

Just came across this problem might be interesting in many applications, for example,
I have a vector A = [2; 5; 10], the values in vector A is sorted and unique.
I have got a matrix (2D or 3D), for example, B = [2, 8, 10; 2, 5, 5; 9, 1, 10];
Want to get a matrix C = [1, 0, 1; 1, 1, 1; 0, 0, 1].
It means if the element in B is also an element of A, we set it to one; otherwise, set the value to zero.
I did this in a for-loop, but for a large 3D matrix, it takes a long time to finish the loop.
Just wondering if there is a smarter method to do this without 'for' loop.
C = zeros(size(B));
for i = 1:size(A,1)
a = A(i);
C(B==a) = 1;
end
This is exactly what ismember does:
A = [2; 5; 10];
B = [2, 8, 10; 2, 5, 5; 9, 1, 10];
C = ismember(B,A)
C =
1 0 1
1 1 1
0 0 1
From the documentation:
ismember(A,B) returns an array containing 1 (true) where the data in A
is found in B. Elsewhere, it returns 0 (false).

Create a matrix according to a binary matrix

Here I got
A = [1, 2, 3]
B = [1, 0, 0, 1, 0, 1]
I want to create a matrix
C = [1, 0, 0, 2, 0, 3]
You can see B is like a mask, The number of ones in B is equal to the number of elements in A. What I want is arrange elements in A to the place where B is 1.
Any method without loop?
Untested, but should be close:
C = zeros(size(B));
C(logical(B)) = A;
This relies on logical indexing.

Intersection of matrices in matlab?

It is almost the same question as this one Matrices intersection!
The difference is this: If the intersection of the element (i, j) of all matrices is the same number then do not output -1 but output this number. An example is the following:
A1 = [2, 2, 0;
2, 2, 0;
0, 2, 0];
A2 = [2, 0, 4;
4, 3, 0;
0, 0, 1];
A3 = [2, 0, 0;
1, 0, 3;
3, 4, 3];
I want to get the follow matrix:
B = [2, 2, 4;
-1, -1, 3;
3, -1, -1];
Version 1
out1 = -1.*(A1~=A2).*(A1~=A3).*(A2~=A3)
max_mat = max(cat(3,A1,A2,A3),[],3)
out1(~out1) = max_mat(~out1)
Output
out1 =
2 2 4
-1 -1 3
3 -1 -1
Version 2: Maybe a faster version
Assumption - If out of the three elements in the corresponding positions across A1, A2 and A3, only two are same, then take the max of those three elements for the final matrix, B.
Code
%%// Concatenate all three A matrices
A=cat(3,A1,A2,A3,A1);
%%// Logical matrix with ones where all three elements are different from each other
out1 = -1.*all(diff(A,[],3)~=0,3)
%%// Get the max values, to be stored where -1 all three corresponding elements
%%// are not different from each other
max_mat = max(A,[],3)
%%// Get the final output
out1(~out1) = max_mat(~out1)
This produces the same output as the previous version.
Version 3
Assumption - If out of the three elements in the corresponding positions across A1, A2 and A3, only two are same, then take the element that is different from the other two for the final matrix, B.
Code
A=cat(3,A1,A2,A3,A1);
AA = A(:,:,1:3);
t1 = bsxfun(#ne,AA,mode(AA,3));
out1 = max(AA.*t1,[],3) + all(~t1,3).*A1;
out1(all(diff(A,[],3)~=0,3))=-1;
This produces the same output as the previous versions.
I would do this
A = A1+A2+A3;
B = (A1==A2)&(A1==A3);
C = (A1==0)+(A2==0)+(A3==0);
D = ones(3)*-1;
D(B==1) = A1(B==1);
D(C==2) = A(C==2);
B records the position of the elements whose number is same for all the matrices.
C records the position of the elements where two of the matrices have 0.
Then we can modify the elements of D, whose values are set -1 initially, using the information in matrices B and C.
A1 = [2, 2, 0;
2, 2, 0;
0, 2, 0];
A2 = [2, 0, 4;
4, 3, 0;
0, 0, 1];
A3 = [2, 0, 0;
1, 0, 3;
3, 4, 3];
A=cat(3,A1,A2,A3);
%identify all fields with identical values on the 3rd dimension
[X,Y]=find(sum(abs(diff(A,1,3)),3)==0);
%delete all but the first repetition, then use the previous code
A(X,Y,2:end)=0;
L=(sum(A~=0,3)>1);
L*-1+(1-L).*sum(A,3)
/update: Had to fix the code, now it should be correct.