Removing all rows from matrix A in matrix B - arrays

I have in MATLAB a matrix A with RGB-values, lets say
A = [1 2 3;
4 5 6;
7 8 9]
and a matrix B lets say
B = [1 2 3;
2 2 2]
Now I want to remove all rows of B from A.
The result would be:
A* = [4 5 6;
7 8 9]
How can this be done efficiently in MATLAB?

To find which rows of A are present in B:
rowmatches = ismember(A,B,'rows')
The above gives a binary vector the length of the number of rows in A. You can then ask for the subset of A rows that were not in B:
output = A(~rowmatches,:)

Related

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)

Collapsing matrix into columns

I have a 2D matrix where the № of columns is always a multiple of 3 (e.g. 250×27) - due to a repeating organisation of the results (A,B,C, A,B,C, A,B,C, and so forth). I wish to reshape this matrix to create a new matrix with 3 columns - each containing the aggregated data for each type (A,B,C) (e.g. 2250×3).
So in a matrix of 250×27, all the data in columns 1,4,7,10,13,16,19,22,25 would be merged to form the first column of the resulting reshaped matrix.
The second column in the resulting reshaped matrix would contain all the data from columns 2,5,8,11,14,17,20,23,26 - and so forth.
Is there a simple way to do this in MATLAB? I only know how to use reshape if the columns I wanted to merge were adjacent (1,2,3,4,5,6) rather than non-adjacent (1,4,7,10,13,16) etc.
Shameless steal from #Divakar:
B = reshape( permute( reshape(A,size(A,1),3,[]), [1,3,2]), [], 3 );
Let A be your matrix. You can save every third column in one matrix like:
(Note that you don't have to save them as matrices separately but it makes this example easier to read).
A = rand(27); %as test
B = A(:,1:3:end);
C = A(:,2:3:end);
D = A(:,3:3:end);
Then you use reshape:
B = reshape(B,[],1);
C = reshape(C,[],1);
D = reshape(D,[],1);
And finally put it all together:
A = [B C D];
You can just treat every set of columns as a single item and do three reshapes together. This should do the trick:
[save as "reshape3.m" file in your Matlab folder to call it as a function]
function out = reshape3(in)
[~,C]=size(in); % determine number of columns
if mod(C,3) ~=0
error('ERROR: Number of rows must be a multiple of 3')
end
R_out=numel(in)/3; % number of rows in output
% Reshape columns 1,4,7 together as new column 1, column 2,5,8 as new col 2 and so on
out=[reshape(in(:,1:3:end),R_out,1), ...
reshape(in(:,2:3:end),R_out,1), ...
reshape(in(:,3:3:end),R_out,1)];
end
Lets suppose you have a 3x6 matrix A
A = [1 2 3 4 5 6;6 5 4 3 2 1;2 3 4 5 6 7]
A =
1 2 3 4 5 6
6 5 4 3 2 1
2 3 4 5 6 7
you extract the size of the matrix
b =size(A)
and then extract each third column for a single row
c1 = A((1:b(1)),[1:3:b(2)])
c2 = A((1:b(1)),[2:3:b(2)])
c3 = A((1:b(1)),[3:3:b(2)])
and put them in one matrix
A_result = [c1(:) c2(:) c3(:)]
A_result =
1 2 3
6 5 4
2 3 4
4 5 6
3 2 1
5 6 7
My 2 cents:
nRows = size(matrix, 1);
nBlocks = size(matrix, 2) / 3;
matrix = reshape(matrix, [nRows 3 nBlocks]);
matrix = permute(matrix, [1 3 2]);
matrix = reshape(matrix, [nRows * nBlocks 1 3]);
matrix = reshape(matrix(:), [nRows * nBlocks 3]);
Here's my 2 minute take on it:
rv = #(x) x(:);
ind = 1:3:size(A,2);
B = [rv(A(:,ind)) rv(A(:,ind+1)) rv(A(:,ind+2))];
saves a few ugly reshapes, may be a bit slower though.
If you have the Image Processing Toolbox, im2col is a very handy solution:
out = im2col(A,[1 4], 'distinct').'
Try Matlab function mat2cell, I think this form is allowed.
X is the "start matrix"
C = mat2cell(X, [n], [3, 3, 3]); %n is the number of rows, repeat "3" as many times as you nedd
%extract every matrix
C1 = C{1,1}; %first group of 3 columns
C2 = C{1,2}; %second group of 3 columns
%repeat for all your groups
%join the matrix with vertcat
Cnew = vertcat(C1,C2,C3); %join as many matrix n-by-3 as you have

Generate vectors from single values in Matlab

I have vector c:
c = [2 5 3];
I want to generate vectors with their lengths equal to each value in c in a consecutive order. So, I should obtain 3 vectors:
c1 = [1 2];
c2 = [3 4 5 6 7];
c3 = [8 9 10];
Next, I want to align these vectors in a 1x3 cell array:
out = {c1 c2 c3};
This may seem straightforward, but I can't figure how to do it automatically. Any ideas?
You could use mat2cell to accomplish this. We first create an array from 1 to sum(c) and then use mat2cell to group the array into pieces where each piece is the size of each element of c.
out = mat2cell(1:sum(c), 1, c);
This reduces the need for intermediate variables and gives you your cell array directly.
out{1} =
1 2
out{2} =
3 4 5 6 7
out{3} =
8 9 10

Matlab reshape horizontal cat

Hi I want to reshape a matrix but the reshape command doesn't order the elements the way I want it.
I have matrix with elements:
A B
C D
E F
G H
I K
L M
and want to reshape it to:
A B E F I K
C D G H L M
So I know how many rows I want to have (in this case 2) and all "groups" of 2 rows should get appended horizontally. Can this be done without a for loop?
You can do it with two reshape and one permute. Let n denote the number of rows per group:
y = reshape(permute(reshape(x.',size(x,2),n,[]),[2 1 3]),n,[]);
Example with 3 columns, n=2:
>> x = [1 2 3; 4 5 6; 7 8 9; 10 11 12]
x =
1 2 3
4 5 6
7 8 9
10 11 12
>> y = reshape(permute(reshape(x.',size(x,2),n,[]),[2 1 3]),n,[])
y =
1 2 3 7 8 9
4 5 6 10 11 12
Cell array approach -
mat1 = rand(6,2) %// Input matrix
nrows = 3; %// Number of rows in the output
[m,n] = size(mat1);
%// Create a cell array each cell of which is a (nrows x n) block from the input
cell_array1 = mat2cell(mat1,nrows.*ones(1,m/nrows),n);
%// Horizontally concatenate the double arrays obtained from each cell
out = horzcat(cell_array1{:})
Output on code run -
mat1 =
0.5133 0.2916
0.6188 0.6829
0.5651 0.2413
0.2083 0.7860
0.8576 0.3032
0.1489 0.4494
out =
0.5133 0.2916 0.5651 0.2413 0.8576 0.3032
0.6188 0.6829 0.2083 0.7860 0.1489 0.4494

Reorder a matrix according to the mean of its rows

Given a matrix A m x n I would like to reorganize its rows so that going from row 1 to row n there is a growing mean value over the row.
Is there a simple way of doing so?
E.g. Input A = [5 5 5; 3 3 3; 2 2 2; 4 4 4] Output B = [2 2 2; 3 3 3; 4 4 4; 5 5 5]
I think you mean rows, not columns; and mean, not median:
[~, ind] = sort(mean(A.')); %'// get indices of sorting the row means
B = A(ind,:); %// apply that sorting to the matrix
(you may save some time using sum instead of mean).
If you really mean columns:
[~, ind] = sort(mean(A));
B = A(:,ind);
If you really mean median, replace mean by median.

Resources