64

When casting a NumPy Not-a-Number value as a boolean, it becomes True, e.g. as follows.

>>> import numpy as np
>>> bool(np.nan)
True

This is the exact opposite to what I would intuitively expect. Is there a sound principle underlying this behaviour?

(I suspect there might be as the same behaviour seems to occur in Octave.)

rroowwllaanndd
  • 3,858
  • 1
  • 22
  • 20
  • 1
    My hunch: NaN is not equal to zero, so it's true when converted to boolean. If NaN were false, then conversion of floats to booleans would take two checks, one for zero and one for NaN. (But I suspect interpreting Numpy floats as booleans is not common practice anyway...) – Fred Foo Mar 28 '13 at 15:50
  • 7
    This is also the case in C (on which NumPy is based). From the standard: `When any scalar value is converted to _Bool, the result is 0 if the value compares equal to 0; otherwise, the result is 1.` Footnote 59 explicitly states that `NaNs do not compare equal to 0 and thus convert to 1.` – jerry Mar 28 '13 at 15:57

5 Answers5

43

This is in no way NumPy-specific, but is consistent with how Python treats NaNs:

In [1]: bool(float('nan'))
Out[1]: True

The rules are spelled out in the documentation.

I think it could be reasonably argued that the truth value of NaN should be False. However, this is not how the language works right now.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 4
    TL;DR for linked docs: Python treats everything as `True` unless it is one of the specifically defined false cases (e.g., `None`, `False`, numeric zeroes, empty sequences, *user-defined* classes that return one of these, etc.). – Kardo Paska Jul 17 '20 at 20:05
  • 1
    I think it should be NaN in all types. That is, boolean should have a NaN value. NaN should never cast to a valid value. – Michael Tuchman Sep 17 '20 at 16:20
8

Python truth-value testing states that the following values are considered False:

  • zero of any numeric type, for example, 0, 0L, 0.0, 0j.

Numpy probably chose to stick with this behaviour and prevent NaN from evaluating to False in a boolean context. Note however that you can use numpy.isnan to test for NaN.

icecrime
  • 74,451
  • 13
  • 99
  • 111
4

0.0 is the only falsy float value because that's what the language designers decided would be most useful. Numpy simply follows along. (It would be weird to have bool(np.nan) be False when bool(float('nan')) is True).

I think it is probably because that's how things work with integers. Admittedly, integers have no NaN or inf types of values, but I suppose that special cases aren't special enough to break the rules.

mgilson
  • 300,191
  • 65
  • 633
  • 696
  • It's not up to the language designers; the Numpy folks could have decided to make `nan` false as well. – Fred Foo Mar 28 '13 at 15:52
  • @larsmans -- Fair enough. I didn't notice that `numpy` was part of the OP's question. I don't think that really changes anything though. It just makes sense for `numpy` to do what python does. – mgilson Mar 28 '13 at 15:56
  • 1
    Should note that -0.0 is also False. It's a thing that may at first not be trivial. – Jostikas Oct 31 '16 at 17:35
2

Numpy follows the python standard for truth testing here, any numeric type evaluates to False if and only if its numerical value is zero.

Note that truth testing with NaN values can be unintuitive in other ways as well (e.g., nan == nan evaluates to False).

Kelsey
  • 992
  • 7
  • 7
0

This is usually needed when testing variables for np.nan. While np.nan is not np.nan fails (evaluates to False), the np.isnan function works (evaluates to True, so can be used to test for np.nan):

np.isnan(np.nan)

True

mirekphd
  • 4,799
  • 3
  • 38
  • 59