conditional deletion of riws

Dear Matlab users, I am writing a matlab script to delete some rows based on some condition. I want to look for some symmetric matrix around a diagonal line of "ones"
(1). I want, in each row, to look for elements which are > 0.7 but less than 1.0.
if there is a value in row "i" and column "j" which satisfies this condition. There should be cell with the same value in row "j" and column "i".
I want to compare these two rows (for each case the conditions are satisfied) and delete the one that has the larger value in the last column for each.
I am writing the script shown below but it does not delete any line and I do not understand why. Would you please advice????? Regards Shireen
M = xlsread('test.xlsx');
[r,c]=size(M);
for i =1:r,
for j=1:c-1
if (M(i,j) >= 0.7) & (M(i,j)<0.1) % get row and column index of points > 0.7
M(i,c)
M(j,c)
if M(i,c)>M(j,c)
nM(i,:)=[ ] % delete the row with the larger "c" value
else
nM(j,:)=[ ]
end
end
end
end

 Accepted Answer

It would be so much easier to read your code if you'd use the code formatting button: {} Code.
I see several issues with your code:
  1. You never define nM
  2. Your first if test is wrong. You're testing if a value is greater than 0.7 and smaller than 0.1 instead of 1.0. That condition will never be true.
  3. Once a row has been deleted your row index is out of sync with the actual rows of nM. For example let's say you delete row 4. the new row 4 is the original row 5, the new row 5 is the old row 6, etc. If you then decide to delete row 5, you're actually deleting the original row 6. You must only perform the deletion after the loop.
  4. You only need to iterate over the upper or lower diagonal of the matrix, since it's symmetric. It may be what you were trying to do, but the upper bound of the 2nd loop should have read i-1 not c-1.
I believe the following should work
[r, c] = size(M);
todelete = [];
for row = 1:r %I prefer more descriptive variable names than i
for col = 1:row-1 %I prefer more descriptive variable names than j
if M(row, col) >= 0.7 && m(row, col) < 1.0
if M(row, end) > M(col, end)
todelete = [todelete row];
else
todelete = [todelete col];
end
end
end
end
nM = M(setdiff(1:r, todelete), :);

5 Comments

You could of course also vectorise the code:
triM = tril(M); %lower diagonal
[r, c] = find(triM >= 0.7 & triM < 1.0); %find position of all values in range
deleterow = M(r, end) > M(c, end); %compare row r with respective row c
%a true in deleterow means delete respective r, otherwise delete respective c
todelete = unique([r(deleterow) c(~deleterow)]);
nM = M;
nM(todelete, :) = [];
Guillaume
Guillaume on 11 Nov 2014
Edited: Guillaume on 11 Nov 2014
Answer to Shelin's question: I wonder if you can explain the command line todelete = unique([r(deleterow) c(~deleterow)]); ?
deleterow is a logical array of true (1) and false (0) values. When an element is true, the corresponding row in r must be deleted, when it is false, it is the corresponding row in c that must be deleted.
r(deleterow) returns only the elements of r where deleterow is true, thus just the rows in r that must be deleted.
c(~deleterow) returns only the elements of c where deleterow is false (or when ~deleterow is true, ~ is logical negation), thus just the rows in c that must be deleted.
[r(deleterow) c(~deleterow)] is thus the concatenation of the two, that is all the rows that must be deleted. unique just remove duplicates.
Hi @Guillaume
a question about your script, which work fine for test file!but is there any chance that a row that we gonna to delete, get false in next compare , will it still be deleted? how can i skip those rows that i already delete? as another way we try :
[M,text,alldata]=xlsread('test2.csv'); % M is numeric date
% text is the text :-)
% all data is both M + text
[r c]=size(M);
S=sum(M,2); %sum rows
good_ones = ones(1,size(M,1));
% loop over rows
for row=1:r;
for col=row+1:c;
if good_ones(row)==1
if (M(row,col) >= 0.7) & (M(row,col) <1.0 ); %if the value between 0.7 to 1 then we compare the sum column
if S(row)>S(col) % if the sum of the i line is larger we delete this line
good_ones(row) = 0;
else % the sum of the j line is larger so we delete the other line
good_ones(col) = 0;
end
end
% mark lines for deletion afterwards
end
end
end
new_M = M(find(good_ones),:);
>> here we enter the loop only if good_ones=1 if it gets a 0 it will skip this row and won't compare it again, is there a way to do it in your way?
Shayma,
You would be better off starting a new question, as people don't tend look at questions marked as answered.
I don't really understand your question (but I've forgotten the details of the original question now), so you'll want to add an example as well.
Shayma's "Answer" moved here so he can Accept Guillaume's answer:
Dear Guillaume, Thank you very much for your answer. I am sorry for the typos in my post.
I wonder if you can explain what the command line shown below works?
"todelete = unique([r(deleterow) c(~deleterow)]);"
I have read the page of the unique command but I am not sure if I got the lines you are writing.
Many Thanks Shireen

Sign in to comment.

More Answers (1)

if (M(i,j)>=0.7) & (M(i,j)<0.1)
The above is impossible...you wrote "0.1" for "1.0" in the second comparison

1 Comment

I am sorry, it was a typo! Thanks for the note.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!