eXistanCe
eXistanCe

Reputation: 735

Numpy division by 0 workaround

lets say I have two arrays

x = [1,2,3]
y = [0,1,0]

I need to divide the arrays element-wise, thus using numpy. My issue is the "secure division" implemented. when doing:

np.divide(x,y).tolist()

I get the output:

[0.0, 2.0, 0.0]

My problem with this is that I need it to return the element that is not 0 when it divides by 0, making the ideal output:

[1.0, 2.0, 3.0]

Is there any workaround to do this using numpy? Manually defining a function to do this, is there any optimized way to do this, without making a custom divide function (like the following) and using it on every pair of elements?

def mydiv(x, y):
if y == 0:
    return x
else:
    return x / y

NOTE: the reason Im worried about optimization is that this will run in the cloud, so resources are limited, and when having 300+ element arrays, doing this does not seem optimal at all.

Upvotes: 5

Views: 914

Answers (2)

user3483203
user3483203

Reputation: 51165

A simple trick you can use:

x / (y + (y==0))

In action:

x = np.array([1, 5, 3, 7])
y = np.array([0, 2, 0, 4])

print(x / (y + (y==0)))

# [1.   2.5  3.   1.75]

Timings:

def chrisz(x, y):
  return x/(y+(y==0))

def coldspeed1(x, y):
  m = y != 0
  x[m] /= y[m]
  return x

def coldspeed2(x, y):
  m = ~(y == 0)
  x[m] /= y[m]
  return x

def coldspeed3(x, y):
  m = np.flatnonzero(y)
  x[m] /= y[m]
  return x

Results:

In [33]: x = np.random.randint(10, size=10000).astype(float)

In [34]: y = np.random.randint(3, size=10000).astype(float)

In [35]: %timeit chrisz(x, y)
29.4 µs ± 601 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [36]: %timeit coldspeed1(x, y)
173 µs ± 2 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [37]: %timeit coldspeed2(x, y)
184 µs ± 1.36 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

In [38]: %timeit coldspeed3(x, y)
179 µs ± 2.68 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

Upvotes: 5

cs95
cs95

Reputation: 402263

The easiest/fastest way to do this would be to just divide the values corresponding to a non-zero y-val.

x = [1, 2, 3]
y = [0, 1, 0]

x, y = [np.array(arr, dtype=float) for arr in (x, y)]

m = y != 0  # ~(y == 0) # np.flatnonzero(y)
x[m] /= y[m]

print(x)
array([1., 2., 3.])

Upvotes: 4

Related Questions