How to vectorize a function which contains an if statement?

arrays, numpy, python, vectorization

Solution

One way is to convert `x` and `y` to numpy arrays inside your function:

def f(x, y):
    x = np.array(x)
    y = np.array(y)
    return np.where(y == 0, 0, x/y)

This will work when one of `x` or `y` is a scalar and the other is a numpy array. It will also work if they are both arrays that can be broadcast. It won't work if they're arrays of incompatible shapes (e.g., 1D arrays of different lengths), but it's not clear what the desired behavior would be in that case anyway.

Problem

Let's say we have the following function: ``` def f(x, y): if y == 0: return 0 return x/y ``` This works fine with scalar values. Unfortunately when I try to use numpy arrays for `x` and `y` the comparison `y == 0` is treated as an array operation which results in an error: ``` --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-13-9884e2c3d1cd> in <module>() ----> 1 f(np.arange(1,10), np.arange(10,20)) <ipython-input-10-fbd24f17ea07> in f(x, y) 1 def f(x, y): ----> 2 if y == 0: 3 return 0 4 return x/y ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() ``` I tried to use `np.vectorize` but it doesn't make a difference, the code still fails with the same error. `np.vectorize` is one option which gives the result I expect. The only solution that I can think of is to use `np.where` on the `y` array with something like: ``` def f(x, y): np.where(y == 0, 0, x/y) ``` which doesn't work for scalars. Is there a better way to write a function which contains an if statement? It should work with both scalars and arrays.

Original source