Find duplicates in a matrix - matlab

consider a matrix:
a = [1 2
1 3
2 3
4 5
6 1]
I want to find duplicates for every unique element of a and take the rows of them to different matrices. For example here lets say that the answer for number 1 is:
a1 = [1 2
1 3
6 1]
The answer for number 2 is:
a2 = [1 2
2 3]
The answer for number 3 is:
a3 = [1 3
2 3]
and so on for every unique elements of matrix a. Any suggestions?

This will do it:
temp=unique(a);
for k=1:numel(temp)
[r,~]=find(a==temp(k));
assignin('base', ['a' num2str(k)], a(sort(r),:))
end
Results:-
>> a1
a1 =
1 2
1 3
6 1
>> a2
a2 =
1 2
2 3
>> a3
a3 =
1 3
2 3
>> a4
a4 =
4 5
>> a5
a5 =
4 5
>> a6
a6 =
6 1

You can use any to check if any element of a row contains the value you want. This will return a logical array that is true where the row contained the value. You can then use this to grab the relevant rows of a.
result = a(any(a == value, 2), :);
We could create an anonymous function that does this for you.
rows_that_contain_value = #(A, value)A(any(A == value, 2), :);
Then we can use this like this
a = [1 2
1 3
2 3
4 5
6 1]
a1 = rows_that_contain_value(a, 1);
a2 = rows_that_contain_value(a, 2);
a3 = rows_that_contain_value(a, 3);
If we want to do this for all unique values in a, we can do something like the following.
groups = arrayfun(#(x)rows_that_contain_value(a, x), unique(a), 'uniformoutput', 0);

Related

how to get number of rows in matlab?

I want to select 2 minimum elements from every column of matrix. How to can display number of row?
input:
a1 a2 a3
--------
b1 2 4 8
b2 8 5 3
b3 1 5 9
output:
a1 a2 a3 a1 a2 a3
-------- ----------
1 4 3 => b3 b1 b2
2 5 8 b1 b2 b1
my code:
for i = 1:3
MINN(:,i)=getNElements(distance(i,:), 1);
end
function [smallestNElements smallestNIdx] = getNElements(A, n)
[ASorted AIdx] = sort(A);
smallestNElements = ASorted(1:n);
smallestNIdx = AIdx(1:n);
end
Let me guess, is this what you want to do?
x = [2 4 8; 8 5 3; 1 5 9]; % data
n = 2; % desired number of smallest values per column
[y, ind] = sort(x,1); % sort each column and get indices of that sorting
y = y(1:n,:); % keep n smallest
ind = ind(1:n,:); % keep their indices
Results:
y =
1 4 3
2 5 8
ind =
3 1 2
1 2 1

Making a match-and-append code more efficient without 'for' loop

I am trying to match 1st column of A with 1st to 3rd columns of B, and append corresponding 4th column of B to A.
For example,
A=
1 2
3 4
B=
1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5
I compare A(:,1) and B(:, 1:3)
1 and 3 are in A(:,1)
1 is in the 1st, 2nd, 3rd rows of B(:, 1:3), so append B([1 2 3], 4:end)' to A's 1st row.
3 is in the 2nd and 4th rows of B(:,1:3), so append B([2 4], 4:end)' to A's 2nd row.
So that it becomes:
1 2 5 4 5 3 1 2
3 4 5 3 6 5 0 0
I could code this using only for and if.
clearvars AA A B mem mem2 mem3
A = [1 2 ; 3 4]
B = [1 2 4 5 4; 1 2 3 5 3; 1 1 1 1 2; 3 4 5 6 5]
for n=1:1:size(A,1)
mem = ismember(B(:,[1:3]), A(n,1));
mem2 = mem(:,1) + mem(:,2) + mem(:,3);
mem3 = find(mem2>0);
AA{n,:} = horzcat( A(n,:), reshape(B(mem3,[4,5])',1,[]) ); %'
end
maxLength = max(cellfun(#(x)numel(x),AA));
out = cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false))
I am trying to make this code efficient, by not using for and if, but couldn't find an answer.
Try this
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
row2 = mat2cell(permute(sum(ab==b,2),[3,1,2]),ones(1,numel(a)));
AA = cellfun(#(x)(reshape(B(x>0,4:end)',1,numel(B(x>0,4:end)))),row2,'UniformOutput',0);
maxLength = max(cellfun(#(x)numel(x),AA));
out = cat(2,A,cell2mat(cellfun(#(x)cat(2,x,zeros(1,maxLength-length(x))),AA,'UniformOutput',false)))
UPDATE Below code runs in almost same time as the iterative code
a = A(:,1);
b = B(:,1:3);
z = size(b);
b = repmat(b,[1,1,numel(a)]);
ab = repmat(permute(a,[2,3,1]),z);
df = permute(sum(ab==b,2),[3,1,2])';
AA = arrayfun(#(x)(B(df(:,x)>0,4:end)),1:size(df,2),'UniformOutput',0);
AA = arrayfun(#(x)(reshape(AA{1,x}',1,numel(AA{1,x}))),1:size(AA,2),'UniformOutput',0);
maxLength = max(arrayfun(#(x)(numel(AA{1,x})),1:size(AA,2)));
out2 = cell2mat(arrayfun(#(x,i)((cat(2,A(i,:),AA{1,x},zeros(1,maxLength-length(AA{1,x}))))),1:numel(AA),1:size(A,1),'UniformOutput',0));
How about this:
%# example data
A = [1 2
3 4];
B = [1 2 4 5 4
1 2 3 5 3
1 1 1 1 2
3 4 5 6 5];
%# rename for clarity & reshape for algorithm's convenience
needle = permute(A(:,1), [2 3 1]);
haystack = B(:,1:3);
data = B(:,4:end).';
%# Get the relevant rows of 'haystack' for each entry in 'needle'
inds = any(bsxfun(#eq, haystack, needle), 2);
%# Create data that should be appended to A
%# All data and functionality in this loop is local and static, so speed
%# should be optimal.
append = zeros( size(A,1), numel(data) );
for ii = 1:size(inds,3)
newrow = data(:,inds(:,:,ii));
append(ii,1:numel(newrow)) = newrow(:);
end
%# Now append to A, stripping unneeded zeros
A = [A append(:, ~all(append==0,1))]

Matlab - find function between matrix and cell array

I’ve a matrix A = (4*4) and a cell array B {4,1}. I’d like to find all the values of B in A, searching row by row and after I’d like to delete the correspondent column associated to this particular value. I’ve a problem using bsxfun o cellfun and find function with a matrix and a cell array. I‘ve tried to convert the cell array into a matrix but I don’t have more the exact correspondence.
For example:
A =
1 5 10 23
2 4 2 18
3 3 5 14
1 9 10 4
B =
1
2 4
3 3 14
1
To obtain:
C =
10
2
5
10
Thanks in advance,
L.
Here's how:
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
C = A(:, all(~vertcat(C{:})));
The cellfun is fed with two cell arrays: the first one contains the rows of A and second one is B. The anonymous function is the tricky part; it operates on a pair of two corresponding rows as follows:
It employs ismember to check which columns in A contain any of the elements in B.
It uses find to pick only the first N ones, with respect to the number of elements in the B.
It uses sparse as a fancy way of zeroing out the rest of the elements.
For your example it would look like this:
A = [1 5 10 23; 2 4 2 18; 3 3 5 14; 1 9 10 4];
B = {1; [2 4]; [3 3 14]; 1};
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
which yields:
C =
{
[1 0 0 0]
[1 1 0 0]
[1 1 0 1]
[1 0 0 0]
}
After that, it's a simple matter of logical indexing to pick the resulting columns:
C = A(:, all(~vertcat(C{:})));
which in this case should be:
C =
10
2
5
10

how to get values of a matrix in MATLAB where the indices are given in a nx2 array

I have a matrix A of size nRows x nCols.
I have a nx2 matrix B which contains indices of the matrix A.
I want to get the values of A at the indices given in B.
lets say,
B = [1, 2;
2, 3;
3, 4]
A(1,2) = 1
A(2,3) = 2
A(3,4) = 1
I want to know any Matlab command which gives the following, given A and B (I don't want to use loops):
[1 2 1]
I guess this is what you are looking for:
A(sub2ind(size(A),B(:,1),B(:,2)))
This is what you want:
A = [1,2; 3, 4; 5, 6; 7,8; 9,0]; % this is your N by 2 matrix
B = [1,1; 1,2; 2,1; 3, 1; 4,2]; % these are your indexes
A(sub2ind(size(A), B(:,1), B(:,2)))
A =
1 2
3 4
5 6
7 8
9 0
B =
1 1
1 2
2 1
3 1
4 2
ans =
1
2
3
5
8

Expand a matrix with polynomials

Say I have a matrix A with 3 columns c1, c2 and c3.
1 2 9
3 0 7
3 1 4
And I want a new matrix of dimension (3x3n) in which the first column is c1, the second column is c1^2, the n column is c1^n, the n+1 column is c2, the n+2 column is c2^2 and so on. Is there a quickly way to do this in MATLAB?
Combining PERMUTE, BSXFUN, and RESHAPE, you can do this quite easily such that it works for any size of A. I have separated the instructions for clarity, you can combine them into one line if you want.
n = 2;
A = [1 2 9; 3 0 7; 3 1 4];
[r,c] = size(A);
%# reshape A into a r-by-1-by-c array
A = permute(A,[1 3 2]);
%# create a r-by-n-by-c array with the powers
A = bsxfun(#power,A,1:n);
%# reshape such that we get a r-by-n*c array
A = reshape(A,r,[])
A =
1 1 2 4 9 81
3 9 0 0 7 49
3 9 1 1 4 16
Try the following (don't have access to Matlab right now), it should work
A = [1 2 9; 3 0 7; 3 1 4];
B = [];
for i=1:n
B = [B A.^i];
end
B = [B(:,1:3:end) B(:,2:3:end) B(:,3:3:end)];
More memory efficient routine:
A = [1 2 9; 3 0 7; 3 1 4];
B = zeros(3,3*n);
for i=1:n
B(3*(i-1)+1:3*(i-1)+3,:) = A.^i;
end
B = [B(:,1:3:end) B(:,2:3:end) B(:,3:3:end)];
Here is one solution:
n = 4;
A = [1 2 9; 3 0 7; 3 1 4];
Soln = [repmat(A(:, 1), 1, n).^(repmat(1:n, 3, 1)), ...
repmat(A(:, 2), 1, n).^(repmat(1:n, 3, 1)), ...
repmat(A(:, 3), 1, n).^(repmat(1:n, 3, 1))];