# How to find the index of first and last nonzero elements in each column?

18 views (last 30 days)
Rabia Zulfiqar on 22 May 2020
Commented: Image Analyst on 23 May 2020
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?

Show 1 older comment
Rabia Zulfiqar on 22 May 2020
@Image analyst how can I do the same thing in 3D which you have explained in 2D matrix?
Rabia Zulfiqar on 22 May 2020
Like here I have a matrix of 7x4 but if I have a matrix of 7x4x20 then how can I do this?
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
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.
Rabia Zulfiqar on 22 May 2020
Thankyou so much for your explanation:)