MATLAB what lines are different between matrices - matlab

I am trying to find the number of the lines where the values of two matrices are not the same
I found only a way to know the indexs on the not same items by:
find(a~=b)
where a is N*N and b is N*N
How can I know the rows numbers of the not same items
ps
looking for nicer way then
dint the find and then having some vector in a loop filling with
ind2sub(size(A), 6)

You can use max on the logical array of such matches or mis-mistaches in this case along a certain dimension, alongwith find.
If you are looking to find unique row IDs for mismatches, do this -
find(max(a~=b,[],2))
For unique column IDs, just change the dimension specifier -
find(max(a~=b,[],1))
Sample run -
>> a
a =
1 2 2 2 1
1 2 1 1 1
2 2 2 2 1
1 1 2 1 1
>> b
b =
1 2 1 1 2
1 2 1 2 1
2 2 2 2 1
1 1 2 2 2
>> a~=b
ans =
0 0 1 1 1
0 0 0 1 0
0 0 0 0 0
0 0 0 1 1
>> find(max(a~=b,[],2)) %// unique row IDs
ans =
1
2
4
>> find(max(a~=b,[],1)) %// unique col IDs
ans =
3 4 5

here I found an easy way if any one will need it
indexs=find(a~=b)
[~,rows]=ind2sub(size(a),indexs)
rows=unique( sort( rows ) )
now rows are only the different rows

NotSame = 0;
for ii = 1:size(a,1)
if a(ii,:) ~= b(ii,:)
NotSame = NotSame+1;
end
end
This checks it row by row and when a row in a is not the same as the row in b this will increase the count of NotSame. Not the fastest way, I'm sure someone can produce a solution using bsxfun, but I'm not an expert in that.

You can also use the double output of find
[row, col] = find(a~=b)
myrows = unique(row);
You can also have the columns where a & b have different values
mycols = unique(col);

Related

Transform a matrix to a stacked vector where all zeroes after the last non-zero value per row are removed

I have a matrix with some zero values I want to erase.
a=[ 1 2 3 0 0; 1 0 1 3 2; 0 1 2 5 0]
>>a =
1 2 3 0 0
1 0 1 3 2
0 1 2 5 0
However, I want to erase only the ones after the last non-zero value of each line.
This means that I want to retain 1 2 3 from the first line, 1 0 1 3 2 from the second and 0 1 2 5 from the third.
I want to then store the remaining values in a vector. In the case of the example this would result in the vector
b=[1 2 3 1 0 1 3 2 0 1 2 5]
The only way I figured out involves a for loop that I would like to avoid:
b=[];
for ii=1:size(a,1)
l=max(find(a(ii,:)));
b=[b a(ii,1:l)];
end
Is there a way to vectorize this code?
There are many possible ways to do this, here is my approach:
arotate = a' %//rotate the matrix a by 90 degrees
b=flipud(arotate) %//flips the matrix up and down
c= flipud(cumsum(b,1)) %//cumulative sum the matrix rows -and then flip it back.
arotate(c==0)=[]
arotate =
1 2 3 1 0 1 3 2 0 1 2 5
=========================EDIT=====================
just realized cumsum can have direction parameter so this should do:
arotate = a'
b = cumsum(arotate,1,'reverse')
arotate(b==0)=[]
This direction parameter was not available on my 2010b version, but should be there for you if you are using 2013a or above.
Here's an approach using bsxfun's masking capability -
M = size(a,2); %// Save size parameter
at = a.'; %// Transpose input array, to be used for masked extraction
%// Index IDs of last non-zero for each row when looking from right side
[~,idx] = max(fliplr(a~=0),[],2);
%// Create a mask of elements that are to be picked up in a
%// transposed version of the input array using BSXFUN's broadcasting
out = at(bsxfun(#le,(1:M)',M+1-idx'))
Sample run (to showcase mask usage) -
>> a
a =
1 2 3 0 0
1 0 1 3 2
0 1 2 5 0
>> M = size(a,2);
>> at = a.';
>> [~,idx] = max(fliplr(a~=0),[],2);
>> bsxfun(#le,(1:M)',M+1-idx') %// mask to be used on transposed version
ans =
1 1 1
1 1 1
1 1 1
0 1 1
0 1 0
>> at(bsxfun(#le,(1:M)',M+1-idx')).'
ans =
1 2 3 1 0 1 3 2 0 1 2 5

Position from reordering in ascending order in Matlab?

I have a matrix in Matlab of dimension mxn, e.g.
A= [ 1 1 1;
1 1 1;
2 2 2;
0 0 1]
I want to order the rows of A in ascending order and get the position of each row within this order. If I use
[~,~,jj] = unique(A,'rows');
I get
jj=[2;2;3;1]
What I want to get is jj=[2;3;4;1] (or jj=[3;2;4;1]), i.e. even if the first two rows of A are equivalent they should not be associated to the same position jj.
Check sortrows. This sorts your array row-based and gives you an array index that tells you where each row was initially.
[B,index] = sortrows(A);
B =
0 0 1
1 1 1
1 1 1
2 2 2
index =
4
1
2
3
And, as #Divakar pointed out:
[~,out] = intersect(index,1:4);
out =
2 3 4 1
If the elements are integers only, this could be another way -
[~,idx] = sort(A*[0:size(A,2)-1].'*(max(A(:))+1),1) %//'
[~,out] = sort(idx) %//'
Sample run -
>> A
A =
1 1 1
1 1 1
2 2 2
0 0 1
>> [~,idx] = sort(A*[0:size(A,2)-1].'*(max(A(:))+1),1);
[~,out] = sort(idx)
out =
2
3
4
1

How to select specific rows based upon column attribute values in matlab?

I have [sentence cross words] logical matrix where value = 1 shows presence of a word in that sentence and 0 shows absence like as follows:
0 0 1 1
1 0 1 0
0 0 0 1
1 1 0 0
I have done some processing and selected specific words i.e. 2 & 3
result = 2 3
Now, I want to select only those rows in which value of words 2 & 3 are equal to 1 and return there row number as follows:
row = 1 2 4
This should be done for every word that is in result variable - thanks.
Think you are looking for something like this, assuming A as the input binary array -
result = [2 3]; %// select words by IDs
row = find(any(A(:,result),2))
Sample run -
A =
0 0 1 1
1 0 1 0
0 0 0 1
1 1 0 0
row =
1
2
4
For fun-sake, you can also use matrix-multiplication as an alternative approach -
row = find(A(:,result)*ones(numel(result),1))
First choose the columns that you want to extract and create a matrix that concatenates all of these columns together. Next, use any and operate along the columns in combination with find to obtain the desired locations.
Therefore, given your logical matrix stored in X, do:
ind = [2 3];
matr = X(:,ind);
vals = find(any(matr, 2));
With your above example, we get:
vals =
1
2
4

Discard elements in a matrix matlab

I would like to know how discard elements in a matrix in Matlab.
I have a Matrix 'A' that contains all possible combination with 8 persons and for each persons I have three possible choice, for example :
A=[1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2;
1 1 1 1 1 1 1 3;
1 1 1 1 1 1 2 1;
1 1 1 1 1 1 2 2;
1 1 1 1 1 1 2 3;
1 1 1 1 1 1 3 1 ;
....
];
etc.. for all elements.
Now I have a new vector B=[2 2] that contains the values for the first two persons, and I would like to obtain a new matrix from A with all possible combination like above, discarding all combinations that not contains the values of B for the first two persons.
I hope to be clear.
Thanks in advance
This should work:
sizeA = size(A,1); % check how long array A is
index = 1;
for ii=1:sizeA
if ~(A(index,1) == B(1,1)) || ~(A(index,2) == B(1,2)) % if either entry doesn't match
A(index,:) = []; % clear the line
else
index=index+1; % else: move to next line
end
end
Note that it is by no means an elegant solution as it is not easily adapted: the ismember function Divakar suggested in the comments suits that purpose better:
A(ismember(A(:,1:2),[2 2],'rows'),:)
What this does, is that it checks row-wise if the first two entries are equal to [2 2], and only returns those rows. For clarification, this is equivalent to:
indices = ismember(A(:,1:2),[2 2],'rows')
A(indices,:)
Where indices is a column vector containing a 1 at each row where the first two entries match [2 2], and a 0 otherwise.

Count non-zero entries in each column of a matrix

If I have a matrix:
A = [1 2 3 4 5; 1 1 6 1 2; 0 0 9 0 1]
A =
1 2 3 4 5
1 1 6 1 2
0 0 9 0 1
How can I count the number of non-zero entries for each column? For example the desired output for this matrix would be:
2, 2, 3, 2, 3
I am not sure how to do this as size, length or numel do not appear to meet the requirements. Perhaps it would be best to remove zero entries first?
It's simply
> A ~= 0
ans =
1 1 1 1 1
1 1 1 1 1
0 0 1 0 1
> sum(A ~= 0, 1)
ans =
2 2 3 2 3
Here's another solution I can suggest that isn't very speed worthy for dense matrices but quite fast for sparse matrices (thanks #user1877862!). This also would mimic how one might do this in a compiled language, like C or Java, and perhaps for research purposes too. First find the row and column locations that are non zero, then do a histogram on just the column locations to count the frequency of how often you see a non-zero in each column. In other words:
[~,col] = find(A ~= 0);
counts = histc(col, 1:size(A,2));
find outputs the row and column locations of where a matrix satisfies some Boolean condition inside the argument of the function. We ignore the first output as we aren't concerned with the row locations.
The output we get is:
counts =
2
2
3
2
3