18 views (last 30 days)

Hi,Is there any way to find the index of first and last nonzero element in a matrix?

I have this matrix

A=[0 0 0 0

0 0 0 0

1 0 4 8

2 0 5 9

3 1 6 7

0 2 7 0

0 0 0 0]

as the first non zero element in 1st column is 3 and and the last is 5. In the second column the the 12th element is the first non zero and the last one is 13th etc

I want to store these values in a matrix in which each row represents the index of first non zero element and the 2nd row shows the index of last non zero elements.

the answer matrix should be like this:

B=[3 12 17 24

5 13 21 26]

How can I do this??

Thankyou for time and consideration.I really appreaciate your help.Kindly guide me

Image Analyst
on 22 May 2020

You could probably use

A = [0 0 0 0

0 0 0 0

1 0 4 8

2 0 5 9

3 1 6 7

0 2 7 0

0 0 0 0]

[rows, columns] = size(A)

B = zeros(2, columns)

for col = 1 : size(A, 2)

B(1, col) = find(A(:, col), 1, 'first');

B(2, col) = find(A(:, col), 1, 'last');

end

This gives

B =

3 5 3 3

5 6 6 5

which makes sense to me but I'm puzzled as to how you get

B=[3 12 17 24

5 13 21 26]

for your example. Can you explain?

Image Analyst
on 23 May 2020

Oh, you wanted the "linear index" rather than the row index within each column (as I had assumed). If you'd said "linear index" (the proper MATLAB lingo) I would have gotten it as :

A = [0 0 0 0

0 0 0 0

1 0 4 8

2 0 5 9

3 1 6 7

0 2 7 0

0 0 0 0]

[rows, columns] = size(A)

B = zeros(2, columns)

for col = 1 : size(A, 2)

B(1, col) = find(A(:, col), 1, 'first') + rows * (col - 1);

B(2, col) = find(A(:, col), 1, 'last') + rows * (col - 1);

end

B

but it looks like Stephen figured out, and it even works for higher dimension arrays, so just use his answer.

Stephen Cobeldick
on 22 May 2020

Edited: Stephen Cobeldick
on 22 May 2020

This works for any array, 2D, 3D, etc., and returns the requested linear indices:

>> A = [0,0,0,0;0,0,0,0;1,0,4,8;2,0,5,9;3,1,6,7;0,2,7,0;0,0,0,0]

A =

0 0 0 0

0 0 0 0

1 0 4 8

2 0 5 9

3 1 6 7

0 2 7 0

0 0 0 0

>> S = size(A);

>> S(1) = 2;

>> X = A~=0;

>> X = X & (cumsum(X,1)==1 | flipud(cumsum(flipud(X),1))==1);

>> B = reshape(find(X),S)

B =

3 12 17 24

5 13 20 26

Stephen Cobeldick
on 22 May 2020

Rabia Zulfiqar's "Answer" moved here:

Stephen Cobeldick Thanks a lot it works perfectly but can you please explain this to me?

Stephen Cobeldick
on 22 May 2020

Lets look at a simple example using one vector (to save space I will use a row vector, but with your data this applies to each column). How can we identify the first non-zero? Start by identifying all non-zeros:

>> V = [0,0,1,2,3,0,0]

V =

0 0 1 2 3 0 0

>> X = V~=0 % all nonzeros.

X =

0 0 1 1 1 0 0

Note that only the first non-zero has a cummulative sum of 1:

>> cumsum(X)

ans =

0 0 1 2 3 3 3

>> X & cumsum(X)==1

ans =

0 0 1 0 0 0 0

We must include the X & ... because if there is only one non-zero in that vector then all of the trailing zeros will also have a cummulative sum = 1, but we can simply exclude them because they are zero.

To get the last non-zero we do exactly the same, but first flip the columns upside down... and then afterwards flip the result back the right way. That gives the last non-zero in each column.

That gives a simple logical array where each true element is either the first or last non-zero in each column. You can use find on that logical array to trivially return the linear indices of those elements.

Opportunities for recent engineering grads.

Apply Today
## 0 Comments

Sign in to comment.