operando en matriz con condición

Considere el siguiente código,

import numpy as np

xx = np.asarray([1,0,1])

def ff(x):
    return np.sin(x)/x

# this throws an error because of division by zero
# C:\Users\User\AppData\Local\Temp/ipykernel_2272/525615690.py:4: 
# RuntimeWarning: invalid value encountered in true_divide
# return np.sin(x)/x

yy = ff(xx)

# to avoid the error, I did the following
def ff_smart(x):
    if (x==0):
        # because sin(x)/x = 1 as x->0
        return 1
    else:
        return np.sin(x)/x

# but then I cannot do
# yy_smart = ff_smart(xx)
# because of ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

# I therefore have to do:

*yy_smart, = map(ff_smart,xx)
yy_smart = np.asarray(yy_smart)

¿Hay alguna manera (algo de magia numpy) de escribir de ff_smarttal manera que pueda llamarlo sin usar mapy ff_smartpermanezca operable en escalares (matrices no numpy)? Me gustaría evitar el registro de tipos en ff_smart.

Answer

tu puedes hacer:

yy = [np.sin(x)/x if x != 0 else 1 for x in xx]

Si desea usar el poder de numpy, una respuesta diferente, que aún es útil saber, es usar matrices enmascaradas:

# initialize x
x = np.array([2, 3, 1, 0, 2])

# compute the masked array of x, masking out 0s
masked_x = np.ma.array(x, mask= x == 0, dtype=x.dtype)

# perform operation only on non-zero values
y = np.sin(masked_x) / masked_x

# get the value back, filling the masked out values with 1s.
y = np.ma.filled(y, fill_value=1)

Para operaciones condicionales como usted describe, numpy tiene la función numpy where .

Tu puedes hacer

np.where(x==0, 1, np.sin(x)/x)