4

What's the easiest, most Pythonic way to divide one numpy array by another (of the same shape, element-wise) only where both arrays are non-zero?

Where either the divisor or dividend is zero, the corresponding element in the output array should be zero. (This is the default output when the divisor is zero, but np.nan is the default output when the dividend is zero.)

abcd
  • 10,215
  • 15
  • 51
  • 85
  • 2
    What shape do you want the output array to be? What do you want to happen at the positions where one *is* zero? – DSM Nov 29 '13 at 21:34

2 Answers2

5

This still tries to divide by 0, but it gives the correct result:

np.where(b==0, 0, a/b)

To avoid doing the divide-by-zero, you can do:

m = b!=0
c = np.zeros_like(a)
np.place(c, m, a[m]/b[m])
askewchan
  • 45,161
  • 17
  • 118
  • 134
  • Does your first example still try to divide by 0? It looks to me like it attempts `a/b` only where neither is 0 (i.e., where `(a==0) | (b==0)` evaluates to `False`). – abcd Nov 29 '13 at 21:46
  • 1
    No, the array `a/b` is evaluated before being passed to the function, as in any ordinary python function call. Note that having and ignoring the divide-by-zero errors is faster than the alternative. I mostly included it for pedagogy's sake. – askewchan Nov 29 '13 at 21:47
  • Sorry, just to be clear, the second example you included only for pedagogy's sake? – abcd Nov 29 '13 at 21:51
  • Yes, it avoids the warning by never dividing by zero, but both give the same result, and `np.where` is faster. In fact, @mtrw's might be the fastest depending on the length of the array. – askewchan Nov 29 '13 at 21:54
3

I would do it in two lines:

z = x/y
z[y == 0] = 0

As you said, if only the element in x is 0, z will already be 0 at that position. So let NumPy handle that, and then fix up the places where y is 0 by using NumPy's boolean indexing.

mtrw
  • 34,200
  • 7
  • 63
  • 71