find 'last' function not working
4 views (last 30 days)
Show older comments
Vasileios Papavasileiou
on 11 Jul 2022
Answered: Steven Lord
on 11 Jul 2022
Hi,
I am using "find" function to identify the first and last row where no-NaN values can be found in an array, as below. The interesting fact is that while 'first' works fine and returns the first index, the 'last' result is a huge number which even exceeds the number of rows in my array. Any ideas on why this happens? Could it be a bug or am I doing a logical error?
Monotonic_first_index = find(~isnan(Monotonic),1,'first')
Monotonic_last_index = find(~isnan(Monotonic),1,'last');
2 Comments
Accepted Answer
Stephen23
on 11 Jul 2022
Edited: Stephen23
on 11 Jul 2022
"Any ideas on why this happens?"
Yes.
"Could it be a bug or am I doing a logical error? "
You are doing several logical errors.
"I am using "find" function to identify the first and last row ..."
Nope, you are not.
Your code actually FINDs the first/last linear index in your matrix:
linear_index = find(...);
%^^^^^^^^^^^ !!!! one output is a linear index !!!!
If you want FIND to return the row and column indices, then two outputs must be specified:
[row_index,~] = find(...);
%^^^^^^^^^ !!! row index !!!
% ^ unused column index
however that will still be buggy, because FIND searches through the entire matrix linearly (i.e. column-by-column) until it finds the requested condition, which might not be the last row in your sense. Consider this simple matrix:
M1 = [0,1;1,0;1,0;0,0]
[R,C] = find(M1,1,'last')
Does this mean that the last row with any non-zero element is row one? Of course not, that is just the last element in the entire matrix, with all elements taken linearly. We can also see that your approach is also flawed with finding the first row too, as a simple example demonstrates:
M2 = [0,0;0,1;0,1;1,0]
[R,C] = find(M2,1,'first')
Does this mean that the first row with non-zero element is row four? Of course not, that is just the first element of the entire matrix, with all elements taken linearly.
If you want the first/last row containing any non-zero element then you could add some logical operations, e.g. ANY/ALL:
R = find(any(M1,2),1,'last')
Specifically for your question:
M = rand(7,3);
M([3,7,8,19]) = NaN
X = all(~isnan(M),2);
find(X,1,'first')
find(X,1,'last')
1 Comment
More Answers (2)
Bruno Luong
on 11 Jul 2022
Edited: Bruno Luong
on 11 Jul 2022
Beside using 'any'/'all', you might make two modifications to get what you want
[Monotonic_last_row, ~] = find(~isnan(Monotonic.' ),1,'last'); % transpose and 2-output call
0 Comments
Steven Lord
on 11 Jul 2022
Another possible solution, beyond calling find with two output arguments, is to call it with one output then convert the linear index into subscripts using ind2sub. This is particularly useful if the input to find is an N-dimensional array (with N > 2.)
rng default % for reproducibility
A = randi(10, 3, 4, 5);
linearIndices = find(A == 9)
Make a cell array to hold subscripts, one per dimension of the original array.
subscripts = cell(1, ndims(A));
Now fill in the elements of that cell array by treating it as a comma-separated list to call ind2sub with a number of outputs equal to the number of dimensions of A.
[subscripts{:}] = ind2sub(size(A), linearIndices)
Let's spot check one of the elements, say the third one.
r = subscripts{1}(3);
c = subscripts{2}(3);
p = subscripts{3}(3);
shouldBe9 = A(r, c, p);
fprintf("Element A(%d, %d, %d) is %d.\n", r, c, p, shouldBe9)
One final check with the hard-coded values (this is where the rng call comes in handy; I know that any time this example runs the A array will be the same so I can hard-code these values.)
A(2, 4, 2)
0 Comments
See Also
Categories
Find more on Sparse Matrices in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!