I am running in to RuntimeWarning: Invalid value encountered in divide
import numpy
a = numpy.random.rand((1000000, 100))
b = numpy.random.rand((1,100))
You want to be using np.where
. See the documentation.
angles = np.where(norms != 0, dots/norms, -2)
Angles will consist of downs/norms
whenever norms != 0
, and will be -2 otherwise. You will still get the RuntimeWarning, as np.where
will still calculate the entire vector dots/norms
internally, but you can safely ignore it.
You could use angles[~np.isfinite(angles)] = ...
to replace nan
values with some other value.
For example:
In [103]: angles = dots/norms
In [104]: angles
Out[104]: array([[ nan, nan, nan, ..., nan, nan, nan]])
In [105]: angles[~np.isfinite(angles)] = -2
In [106]: angles
Out[106]: array([[-2., -2., -2., ..., -2., -2., -2.]])
Note that division by zero may result in inf
s, rather than nan
s,
In [140]: np.array([1, 2, 3, 4, 0])/np.array([1, 2, 0, -0., 0])
Out[140]: array([ 1., 1., inf, -inf, nan])
so it is better to call np.isfinite
rather than np.isnan
to identify the places where there was division by zero.
In [141]: np.isfinite(np.array([1, 2, 3, 4, 0])/np.array([1, 2, 0, -0., 0]))
Out[141]: array([ True, True, False, False, False], dtype=bool)
Note that if you only want the top ten values from an NumPy array, using the np.argpartition
function may be quicker than fully sorting the entire array, especially for large arrays:
In [110]: N = 3
In [111]: x = np.array([50, 40, 30, 20, 10, 0, 100, 90, 80, 70, 60])
In [112]: idx = np.argpartition(-x, N)
In [113]: idx
Out[113]: array([ 6, 7, 8, 9, 10, 0, 1, 4, 3, 2, 5])
In [114]: x[idx[:N]]
Out[114]: array([100, 90, 80])
This shows np.argpartition
is quicker for even only moderately large arrays:
In [123]: x = np.array([50, 40, 30, 20, 10, 0, 100, 90, 80, 70, 60]*1000)
In [124]: %timeit np.sort(x)[-N:]
1000 loops, best of 3: 233 µs per loop
In [125]: %timeit idx = np.argpartition(-x, N); x[idx[:N]]
10000 loops, best of 3: 53.3 µs per loop
In newer versions of numpy there is a third alternative option that avoids needing to use the errstate context manager.
All Numpy ufuncs accept an optional "where" argument. This acts slightly differently than the np.where function, in that it only evaluates the function "where" the mask is true. When the mask is False, it doesn't change the value, so using the "out" argument allows us to preallocate any default we want.
import numpy as np
angle = np.arange(-5., 5.)
norm = np.arange(10.)
# version 1
with np.errstate(divide='ignore'):
res1 = np.where(norm != 0., angle / norm, -2)
# version 2
with np.errstate(divide='ignore'):
res2 = angle/norm
res2[np.isinf(res2)] = -2
# version 3
res3 = -2. * np.ones(angle.shape)
np.divide(angle, norm, out=res3, where=norm != 0)
print(res1)
print(res2)
print(res3)
np.testing.assert_array_almost_equal(res1, res2)
np.testing.assert_array_almost_equal(res1, res3)
you can ignore warings with the np.errstate
context manager and later replace nans with what you want:
import numpy as np
angle = np.arange(-5., 5.)
norm = np.arange(10.)
with np.errstate(divide='ignore'):
print np.where(norm != 0., angle / norm, -2)
# or:
with np.errstate(divide='ignore'):
res = angle/norm
res[np.isnan(res)] = -2
You can use np.where( condition ) to perform a conditional slice of where norms does not equal 0 before dividing:
norms = np.where(norms != 0 )
angles = dots/norms