Find the count of elements in one matrix equal to another - matlab

I need to compare the elements of two matrices and return a count of how many rows are exactly same. The ismember function returns one column for each column present in the matrix. But I want just one column indicating whether the row was same or not. Any ideas will be greatly appreciated.

If you want to compare corresponding rows of the two matrices, just use
result = all(A==B, 2);
Example:
>> A = [1 2; 3 4; 5 6]
A =
1 2
3 4
5 6
>> B = [1 2; 3 0; 5 6]
B =
1 2
3 0
5 6
>> result = all(A==B, 2)
result =
1
0
1
If you want to compare all pairs of rows:
result = pdist2(A,B)==0;
Example:
>> A = [1 2; 3 4; 1 2]
A =
1 2
3 4
1 2
>> B = [1 2; 3 0]
B =
1 2
3 0
>> result = pdist2(A,B)==0
result =
1 0
0 0
1 0

Related

how to remove the column with all the same elements in matlab?

Suppose the input is:
[1 2 3;
2 3 3;
3 4 3;
3 5 3;]
The expected output would be:
[1 2;
2 3;
3 4;
3 5;]
The reason to remove the third column is because all the elements in the third column is the same. Is there a default matlab function for this?
A(:,sum(abs(diff(A)))>0,1)
"Keep the columns where the difference is larger than zero"
Both the posted answers are incorrect. Test the edge cases where A only has 1 or 2 rows:
i.e:
A = [1 2 3];
or:
A = [1 2 3;
2 3 3];
diff and any need to be supplied with the correct dimension:
A = A(:,any(diff(A,1,1),1));
This outputs:
A = [1 2 3; 2 3 3];
EDU>> A(:,any(diff(A,1,1),1))
ans =
1 2
2 3
and
A = [1 2 3]
EDU>> A(:,any(diff(A,1,1),1))
ans =
Empty matrix: 1-by-0
Also, IMO this, semantically, makes the most sense:
A(:,all(bsxfun(#eq,A,A(1,:)),1)) = []
How about:
A =
1 2 3
2 3 3
3 4 3
3 5 3
B = A==repmat(A(1,:),size(A,1),1)
B =
1 1 1
0 0 1
0 0 1
0 0 1
C = sum(B) == size(A,1)
C =
0 0 1
A(:,C) =[]
A =
1 2
2 3
3 4
3 5
In one line:
A(:, sum(A==repmat(A(1,:),size(A,1),1)) == size(A,1)) = []

take from matrix non-zero rows per column

I have a matrix A. Suppose it is:
A=[1 0 8;
0 0 2;
3 0 5;
4 8 0;
0 5 3;
6 1 3;
1 6 5;
0 7 1]
and I want to get the non-zero rows subscripts per column in a new matrix.
In my example that will be,
B = [ 1 3 4 6 7 0 0 0;
4 5 6 7 8 0 0 0;
1 2 3 5 6 7 8 0]
In terms of just size, if A=(m,n), B will be B=(n,m) (the transpose). In terms of content, B contains the subscripts of the non-zero rows in A as described above.
Here is one way:
mask = ~sort(~A); %// destination of row indexes in output
[ii,~]=find(A); %// get the row indexes
B = zeros(size(A));
B(mask) = ii; B=B.' %'//write indexes to output and transpose
I think this does what you want (get the non-zero row indices per column). It's very similar to this other question:
[r c] = size(A);
M = bsxfun(#times, A~=0, 1:size(A,2)).'; %'// substitute values by indices
[~, rows] = sort(M~=0,'descend'); %//'' push zeros to the end
cols = repmat(1:r,c,1);
ind = sub2ind([c r],rows(:),cols(:));
B = repmat(NaN,c,r);
B(:) = M(ind).';
B = B.';
Result:
>> B
B =
1 3 4 6 7 0 0 0
4 5 6 7 8 0 0 0
1 2 3 5 6 7 8 0

How to find one value from a matrix

0I have on matrix-
A=[1 2 2 3 5 5;
1 5 5 8 8 7;
2 9 9 3 3 5];
From matrix i need to count now many nonzero elements ,how any 1,how many 2 and how many 3 in each row of given matrix"A".For these i have written one code like:
[Ar Ac]=size(A);
for j=1:Ar
for k=1:Ac
count(:,j)=nnz(A(j,:));
d(:,j)=sum(A(j,:)== 1);
e(:,j)=sum(A(j,:)==2);
f(:,j)=sum(A(j,:)==3);
end
end
but i need to write these using on loop i.e. here i manually use sum(A(j,:)== 1),sum(A(j,:)== 2) and sum(A(j,:)== 3) but is there any option where i can only write sum(A(j,:)== 1:3) and store all the values in the different row i.e, the result will be like-
b=[1 2 1;
1 0 0;
0 1 2];
Matlab experts need your valuable suggestions
Sounds like you're looking for a histogram count:
U = unique(A);
counts = histc(A', U)';
b = counts(:, ismember(U, [1 2 3]));
Example
%// Input matrix and vector of values to count
A = [1 2 2 3 5 5; 1 5 5 8 8 7; 2 9 9 3 3 5];
vals = [1 2 3];
%// Count values
U = unique(A);
counts = histc(A', U)';
b = counts(:, ismember(U, vals));
The result is:
b =
1 2 1
1 0 0
0 1 2
Generalizing the sought values, as required by asker:
values = [ 1 2 3 ]; % or whichever values are sought
B = squeeze(sum(bsxfun(#(x,y) sum(x==y,2), A, shiftdim(values,-1)),2));
Here is a simple and general way. Just change n to however high you want to count. n=max(A(:)) is probably a good general value.
result = [];
n = 3;
for col= 1:n
result = [result, sum(A==col, 2)];
end
result
e.g. for n = 10
result =
1 2 1 0 2 0 0 0 0 0
1 0 0 0 2 0 1 2 0 0
0 1 2 0 1 0 0 0 2 0
Why not use this?
B=[];
for x=1:size(A,1)
B=[B;sum(A(x,:)==1),sum(A(x,:)==2),sum(A(x,:)==3)];
end
I'd do this way:
B = [arrayfun(#(i) find(A(i,:) == 1) , 1:3 , 'UniformOutput', false)',arrayfun(#(i) find(A(i,:) == 2) , 1:3 , 'UniformOutput', false)',arrayfun(#(i) find(A(i,:) == 3) , 1:3 , 'UniformOutput', false)'];
res = cellfun(#numel, B);
Here is a compact one:
sum(bsxfun(#eq, permute(A, [1 3 2]), 1:3),3)
You can replace 1:3 with any array.
you can make an anonymous function for it
rowcnt = #(M, R) sum(bsxfun(#eq, permute(M, [1 3 2]), R),3);
then running it on your data returns
>> rowcnt(A,1:3)
ans =
1 2 1
1 0 0
0 1 2
and for more generalized case
>> rowcnt(A,[1 2 5 8])
ans =
1 2 2 0
1 0 2 2
0 1 1 0

Split matrix based on number in first column

I have a matrix which has the following form:
M =
[1 4 56 1;
1 3 5 1;
1 3 6 4;
2 3 5 0;
2 0 0 0;
3 1 2 3;
3 3 3 3]
I want to split this matrix based on the number given in the first column. So I want to split the matrix into this:
A =
[1 4 56 1;
1 3 5 1;
1 3 6 4]
B =
[2 3 5 0;
2 0 0 0]
C =
[3 1 2 3;
3 3 3 3]
I tried this by making the following loop, but this gave me the desired matrices with rows of zeros:
for i = 1:length(M)
if (M(i,1) == 1)
A(i,:) = M(i,:);
elseif (M(i,1) == 2)
B(i,:) = M(i,:);
elseif (M(i,1) == 3)
C(i,:) = M(i,:);
end
end
The result for matrix C is then for example:
C =
[0 0 0 0;
0 0 0 0;
0 0 0 0;
2 3 5 0;
2 0 0 0]
How should I solve this issue?
Additional information:
The actual data has a date in the first column in the form yyyymmdd. The data set spans several years and I want to split this dataset in matrices for each year and after that for each month.
You can use arrayfun to solve this task:
M = [
1 4 56 1;
1 3 5 1;
1 3 6 4;
2 3 5 0;
2 0 0 0;
3 1 2 3;
3 3 3 3]
A = arrayfun(#(x) M(M(:,1) == x, :), unique(M(:,1)), 'uniformoutput', false)
The result A is a cell array and its contents can be accessed as follows:
>> a{1}
ans =
1 4 56 1
1 3 5 1
1 3 6 4
>> a{2}
ans =
2 3 5 0
2 0 0 0
>> a{3}
ans =
3 1 2 3
3 3 3 3
To split the data based on an yyyymmdd format in the first column, you can use the following:
yearly = arrayfun(#(x) M(floor(M(:,1)/10000) == x, :), unique(floor(M(:,1)/10000)), 'uniformoutput', false)
monthly = arrayfun(#(x) M(floor(M(:,1)/100) == x, :), unique(floor(M(:,1)/100)), 'uniformoutput', false)
If you don't know how many outputs you'll have, it is most convenient to put the data into a cell array rather than into separate arrays. The command to do this is MAT2CELL. Note that this assumes your data is sorted. If it isn't use sortrows before running the code.
%# count the repetitions
counts = hist(M(:,1),unique(M(:,1));
%# split the array
yearly = mat2cell(M,counts,size(M,2))
%# if you'd like to split each cell further, but still keep
%# the data also grouped by year, you can do the following
%# assuming the month information is in column 2
yearByMonth = cellfun(#(x)...
mat2cell(x,hist(x(:,2),unique(x(:,2)),size(x,2)),...
yearly,'uniformOutput',false);
You'd then access the data for year 3, month 4 as yearByMonth{3}{4}
EDIT
If the first column of your data is yyyymmdd, I suggest splitting it into three columns yyyy,mm,dd, like below, to facilitate grouping afterward:
ymd = 20120918;
yymmdd = floor(ymd./[10000 100 1])
yymmdd(2:3) = yymmdd(2:3)-100*yymmdd(1:2)

matlab replace number

in a column, value 2 replace with 1 and value 1 & 3 replace with 2. The code i wrote below got problem:
S=[1 1 1 2 2 3 3 3 3];
S(S==2)=1; S(S==1)=2; S(S==3)=2;
result:
S=[2 2 2 2 2 2 2 2 2]
However, the result i wan to get is S=[2 2 2 1 1 2 2 2 2]. does anyone can help?
That is happening because when in the S(S==1)=2; step, you are affected by the modifications from the S(S==2)=1; step. Try this
S = [1 1 1 2 2 3 3 3 3];
S_copy = S;
S(S_copy == 2) = 1; S(S_copy == 1) = 2; S(S_copy == 3) = 2;
or you could also save the results of the tests into separate variables:
S = [1 1 1 2 2 3 3 3 3];
f1 = (S == 2);
f2 = (S == 1);
f3 = (S == 3);
S(f1) = 1; S(f2) = 2; S(f3) = 2;
Instead of manually replacing each value, you can use an extra matrix to define a "map" from input values in S to output values.
>> S = [1 1 1 2 2 3 3 3 3]; % input
>> M = [2 1 2]; % M[i] = j -> map value i to j
>> S = M(S) % compute output
S =
2 2 2 1 1 2 2 2 2
This operation should be really fast in Matlab.
Note that this methods works as long as the values in S can be interpreted as index values (that is, they are integers and not too large).
your are getting closer but the problem arises once you change all the 2's to one.
after this statement
S(S==2)=1;
the array looks like this
S=[1 1 1 1 1 3 3 3 3];
and after the other two statements S(S==1)=2; S(S==3)=2;
your array will obviously have all 2's.
Instead of
S(S==2)=1; S(S==1)=2; S(S==3)=2;
you can do like this:
S(S==2)=-1; S(S==1)=2; S(S==3)=2;S(S==-1)=1;
i.e. in the first step change all the 2's to some other value(e.g. -1 here) and then do the required conversion i.e. S(S==-1)=1;