[Numpy-discussion] Invalid value encoutered : how to prevent numpy.where to do this?

Nathaniel Smith njs@pobox....
Sat Jan 5 08:27:42 CST 2013

On Sat, Jan 5, 2013 at 2:15 PM, Eric Emsellem <eric.emsellem@eso.org> wrote:
> Dear all,
> I have a code using lots of "numpy.where" to make some constrained
> calculations as in:
> data = arange(10)
> result = np.where(data == 0, 0., 1./data)
> # or
> data1 = arange(10)
> data2 = arange(10)+1.0
> result = np.where(data1 > data2, np.sqrt(data1-data2), np.sqrt(data2-data2))
> which then produces warnings like:
> /usr/bin/ipython:1: RuntimeWarning: invalid value encountered in sqrt
> or for the first example:
> /usr/bin/ipython:1: RuntimeWarning: divide by zero encountered in divide
> How do I avoid these messages to appear?
> I know that I could in principle use numpy.seterr. However, I do NOT
> want to remove these warnings for other potential divide/multiply/sqrt
> etc errors. Only when I am using a "where", to in fact avoid such
> warnings! Note that the warnings only happen once, but since I am going
> to release that code, I would like to avoid the user to get such
> messages which are irrelevant here (because I am testing, with the
> where, when NOT to divide by zero or take a sqrt of a negative number).

You can't avoid it while using np.where like this, because the warning
is being issued before np.where is even called. It's basically doing:
  # Calculate all possible sqrts
  tmp1 = np.sqrt(data1-data2)
  tmp2 = np.sqrt(data2-data2)  # let's pretend this isn't just all zeros...
  # Use np.where to pick out the useful ones and put them together
into one array
  mashed_up = np.where(data1 > data2, tmp1, tmp2)

So you need to somehow apply the indexing while doing the sqrt. In
this case the easiest way would just be
  np.sqrt(np.where(data1 > data2, data1 - data2, data2 - data2))
Or, slightly faster (avoiding some temporaries):
  np.sqrt(np.where(data1 > data2, data1, data2) - data2)

If your operation doesn't factor like this though then you can always
use something more cumbersome like
  result = np.empty_like(data)
  mask = (data == 0)
  result[mask] = 0
  result[~mask] = 1.0/data[~mask]

Or in 1.7 this could be written
  result = np.zeros_like(data)
  np.divide(1.0, data, where=(data != 0), out=result)


More information about the NumPy-Discussion mailing list