identifying entry elements in rows of logical matrix

I want to identifiy the entry elements (i.e., the first "1" value) in the rows of the following logical matrix
input_matrix = [1 1 1; 0 1 1; 0 0 0; 0 1 0];
the expected matrix would be the following:
output_matrix = [1 0 0; 0 1 0; 0 0 0; 0 1 0];
The position of the "entries" (first "1" values) in both input and output matrices is respected. Also, Further "1" values (following the entries) have been replaced with "0" values.
Thanks in advance for any hint.

2 Comments

@julian gaviria Just a note -
My and Stephen's code did exactly what was asked.
You should have clarified what exactly you wanted, in your question statement. The comments on my code clearly indicated what the code does, and you should have picked up from them that it is not what you want to do and mentioned it in reply to that.
Nevertheless, @Stephen23 has already provided an answer for your query.
I will be deleting my solution.

Sign in to comment.

 Accepted Answer

A = [1,1,1;0,1,1;0,0,0;0,1,0]
A = 4×3
1 1 1 0 1 1 0 0 0 0 1 0
B = A .* (cumsum(A,2)==1) % replace .* with & to get a logical output
B = 4×3
1 0 0 0 1 0 0 0 0 0 1 0

11 Comments

I thought there should be a no-loop solution. I thought of cumsum() but was looking at accumarray() first.
Any reason why can't use below directly?
A = [1,1,1;0,1,1;0,0,0;0,1,0];
B=cumsum(A,2)==1
B = 4×3 logical array
1 0 0 0 1 0 0 0 0 0 1 1
The last row is not according to the desired output.
Thanks,
Would you mind to let me know your thoughts on why the following elements from the attached logical c1_input matrix were wrongly indexed?
row 4 col 14 (case: 0 1 0)
row 110 col 23 (case: 0 1 1)
As it's shown in the reulting matrix in "c1_output". The "1" values were wrongly replaced by "0".
This error is found in further places with the same cases. I've obtained the same results by using @Stephen23's:
c1_output = c1 .* (cumsum(c1_input,2)==1);
and @Dyuman Joshi's code:
for idx=1:size(c1_input,1)
%find the index of first 1 in the row
z=find(c1_input(idx,:),1);
%update the rest of the elements to 0
c1_input(idx,z+1:end)=0;% the name is then replaced to c1_output.
end
Thank you @Fangjun Jiang as well.
"Would you mind to let me know your thoughts on why the following elements from the attached logical c1_input matrix were wrongly indexed? "
My answer does not use any indexing. But lets take a look at your uploaded data anyway:
S = load('c1_logical.mat')
S = struct with fields:
c1_input: [390×168 logical] c1_output: [390×168 logical]
I = S.c1_input; % your data are actually logical, not numeric.
O = I & (cumsum(I,2)==1); % so I will use & here, not .*
isequal(O, S.c1_output)
ans = logical
1
row 4 col 14 (case: 0 1 0)
I(4,1:20)
ans = 1×20 logical array
0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0
O(4,1:20)
ans = 1×20 logical array
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
We can clearly see that the first "1" in row 4 is in column 9, and that is indeed the only "1" that is given in that row in the output matrix:
find(O(4,:))
ans = 9
I would not expect any "1" elements of the output around column 14 of that row. It is unclear what the problem is.
row 110 col 23 (case: 0 1 1)
I(110,1:26)
ans = 1×26 logical array
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0
O(110,1:26)
ans = 1×26 logical array
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
We can clearly see that the first "1" in row 110 is in column 8, and that is indeed the only "1" that is given in that row in the output matrix:
find(O(110,:))
ans = 8
I would not expect any "1" elements of the output around column 23 of that row. It is unclear what the problem is.
Thanks a lot @Stephen23,
I probably was not clear enough. Taking as example the following row:
0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0
the expected output would be:
0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0
That is why I was talking about "entries". The aim is to raplace with "0" those "1" values preceded by "one" values. Another example would be:
0 0 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0
Expected output:
0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0
P.D. As you rightly pointed it out, the matrices are logical (see also title of the of the question)
Thank you.
"the expected output would be..."
completely different to what you explained in your question. In your question you requested "I want to identifiy the entry elements (i.e., the first "1" value) in the rows of the following logical matrix". You asked for the "first "1" value", so that is exactly what my answer does. You did not mention "groups" or "runs" of 1's, or anything like that.
Now you are asking for something else, like identifying each group of 1's that occur in a row, and considering each group independently. Lets try it now with a better example matrix, with groups like you describe:
A = logical([1,1,0,1,1;0,1,1,0,1;0,0,0,0,0;0,1,1,1,0])
A = 4×5 logical array
1 1 0 1 1 0 1 1 0 1 0 0 0 0 0 0 1 1 1 0
B = diff([0&A(:,1),A],1,2)>0
B = 4×5 logical array
1 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0
This is a briliant code line. It does what I was looking for.
Thank you very much @Stephen23
Apologies for the lack of clarity in the initial request.
I'm just curious what "0&A" does.
Best
"I'm just curious what "0&A" does."
It is my lazy way of creating a column of FALSE values:
0&A(:,1)
^ scalar zero (equivalent to FALSE)
^ logical AND (expands scalar to match array size)
^^^^^ first column of A (values not important)
The values in A are irrelevant because they are ANDed with FALSE. The code is approx. equivalent to:
false(size(A,1),1)
Isn't it funny that my solution was correct after all?
MATLAB works in mysterious ways XD

Sign in to comment.

More Answers (1)

in = [1 1 1; 0 1 1; 0 0 0; 0 1 0];
M=size(in,1);
temp=[zeros(M,1), in];
d=diff(temp,1,2);
out=(d==1)
out = 4×3 logical array
1 0 0 0 1 0 0 0 0 0 1 0

3 Comments

No. This will be a problem for a row like [1 0 1]
This wouldn't work if there is a 1 after a 0
in = [1 1 0 1; 0 1 1 1; 0 0 0 0; 0 0 1 0];
M=size(in,1);
temp=[zeros(M,1), in];
d=diff(temp,1,2);
out=(d==1)
out = 4×4 logical array
1 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0

Sign in to comment.

Products

Release

R2022b

Community Treasure Hunt

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

Start Hunting!