Simple Method for Finding if ANY NaN values occur in a matrix.

Is there a quick method of finding out whether or not a matrix or a vector in matlab has any NaN values? A large matrix filled with mostly 0's (after applying isnan(MATRIX)) does not really cut it.
Don't get me wrong, I would information of finding out where such NaN's occur and how to count how many NaN values appear in a given matrix, but I really would like to know if there is a simple way to identify if any NaN's at all appear in a given matrix with a simple 1 or 0 response, as it would save me time having to inspect the matrix or write a program to do it.
Would there be simple ways of counting how many NaN's occur, and identify their location in a given matrix? I assume such techniques would be applicable to finding infinities as well, am I correct?

 Accepted Answer

Short of a mex routine that can avoid the creation of a potentially large intermediate array, I think you are stuck with isnan( ). E.g., counting the number of NaN's
result = sum(isnan(MATRIX(:)));
Or if you want locations, then find( ) etc.
And yes, you can do similar calculations with the isinf( ) function.
A mex routine to do this would not be too difficult to write, btw ...

19 Comments

Too bad! I was hoping I could get away with working in the command prompt rather than write a routine directly in the program, as it is complicated enough already.
I forgot about the built-in 'sum' command, but your listing just gave me an idea. If the sum is 0, then no NaN values can be in the matrix. If it is anything other than 0, then at least one NaN exists in the matrix. Your suggestion seems to have lead me to figuring out how to quickly decipher if any NaN values exist in the matrix! All I would need to do is check if the final result is equal to 0 after the summation! Thanks for jump-starting my thinking!
nnz() is often faster than sum() for this purpose.
For this result in particular you can do
result = any(isnan(MATRIX(:)));
Or you could use the anyEq mex routine from the FEX by Jan Simon to avoid the intermediate array:
result = anyEq(MATRIX,NaN);
You cannot use anyEq(MATRIX,NaN) because one of the properties of nan is that nan == nan is false.
But you could use
anyEq(isnan(MATRIX),1)
which would create the intermediate matrix but would be fast for the search.
I should have mentioned that anyEq treats NaN's as equal for the purpose of creating a result. I.e., it uses the mxIsNan( ) API function instead of comparing values directly (which would have given a false result if the check had been done this way internally as you pointed out). E.g.,
>> x = [1 nan 3];
>> anyEq(x,NaN)
ans =
1
Also, the speed advantage is not necessarily there for the mex routine since the MATLAB functions any( ) and isnan( ) are probably multi-threaded in the background. So, if the NaN is near the front of the matrix then the mex routine would probably be faster since it short-circuits and avoids the intermediate array. But if the NaN is near the back of the matrix or not present, the MATLAB m-code could very well be faster even though it builds an intermediate array.
Ok, I wrote a function that should be able to handle this, but I keep receiving an 'ans' output and can't seem to figure out why it is not being suppressed. The 'ans' value is giving the sum of the number of NaN terms in the matrix. How would I be able to convert this 'ans' tag to 'sum'. Thus, my function would then output a 1 or 0 for true or false, and yield the sum of NaNs in the matrix.
function f = nanappear(n);
f = sum(isnan(n(:)));
if f == 0 ;
disp('0');
else
disp('1') ;
end
end
So I would like to 1) suppress 'ans' output and 2) learn how to change 'ans' to 'sum'. This problem only appears for me when defining functions for some reason.
I don't understand why you have that if-test in the function at all. That will always print to the screen. You only need that one computation line in the function.
I know, if I wanted the sum alone. Before, I merely just wanted an output of 1 or 0, nothing else. This is why I wrote the if statement. Because it kept giving me 'ans' and I was uncertain exactly how to mitigate it, I thought I would turn this into an extended learning experience with this particular code.
@BMor: The ans was due to how you called the function, not because of how the function was defined: if you do not allocate the output to a variable then ans is the default. That is how MATLAB works. Note that displaying in the command window is slow.
OK, so based on what you are currently trying to do, what exactly would you like your function to output? I.e., how many outputs and what would they be?
@Stephen Cobeldick, @James Tursa: I realize that the output would have to be allocated to a variable, and I have no problem that 'ans' is that variable.
When I call the function: nanappear(n)
I just initially did not want the ans to appear and be listed. Is there a way delete it before it is printed to the screen?
Append a semi-colon to the call, e.g.
result = nanappear(n); % <-- append a semi-colon
If the function has an output argument defined then it will be allocated when the function is called, either to the specified output variable or to ans. It will not be printed if you use a semi-colon:
nanappear(...);
If you do not want ans at all then either:
  • define your function without any output argument, or
  • use nargout to select how many elements varargout returns:
function varargout = nanappear(...)
C = {nnz(...)};
varargout = C(1:nargout);
end
I would not recommend using varargout: it means that the tab completion and f1 help cannot show the output argument names, takes your code farther away from standard MATLAB practice, and means that you cannot test it simply from the command line. Imagine if sin or any other MATLAB function behaved the same way:
>> sin(pi)
>>
@Stephen Cobeldick, Thanks a bunch, the solution is simply to remove f in f = nanappear(n). If I keep everything else the same, it works! I now see what you meant. I assumed I had to define a function in this way. Thanks for the lesson. That is, I defined it now as:
function nanappear(n)
...same arguments...
end
If you define your function this way, the only thing it will really be able to do is print stuff to the screen. Since you don't pass anything back to the caller, that sum of the number of nans you calculated gets thrown away when the function returns. I'm not sure this is really what you want.
It is exactly what I wanted. I am just using this function to test when NaNs first appear in my program. Because I needed to test a whole multitude of different variables, I just wanted an output to say if NaNs were in the variable or not. Then I would move on and test another variable. I figured it was easier to define a function that just performed this test simply and quickly for me, as none existed in MATLAB that did exactly this without adding a whole mess of other junk to my variable list, which would then still require me to sort out.
The other program worked, and did help me find what I wanted, but because I found the function so useful, and imagine others would too, I wanted to clean it up before storing a 'good' copy, and/or giving it to others. I never wrote a function before, but for troubleshooting I now see how wonderful they can be without cluttering the variables list!
function f = nanappear(n)
f = any(isnan(n(:)));
It is rather unlikely that people wanting to use your function will only want the result to be displayed to the screen.
And if that's the case, they can simply define the function f = function_name
as you showed above
I just didn't want to add another variable to the list I already had. Because I was troubleshooting in this particular way, it did me no good to do so either.
"I just didn't want to add another variable to the list I already had"
disp(nanappear(n))
If that is too much, then, Sure, you can use
function nanappear(n)
disp(any(isnan(n(:))));
But I would not expect that other people would find it useful.
Note: I might suggest "anynan" as the function name.

Sign in to comment.

More Answers (3)

Personally I think
any(isnan(your_matrix(:)));
is the easiest way.
Here is a fast C-Mex function to find out, if any element of one array occurs in the other: FEX: anyEq .
hasAnyNaN = anyEq(X, NaN);
This does not create a temporary array like isnan(X) and stops the search at the first match already. So this is treated as efficient as possible:
X = NaN(1, 1e6);
T = anyEq(X, NaN); % Performs 1 comparison only

Products

Asked:

BM
on 20 Mar 2018

Moved:

on 7 May 2024

Community Treasure Hunt

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

Start Hunting!