0

Consider the following code,

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)

Is there a way (some numpy magic) to write ff_smart such that I can call it without using map and ff_smart remains operable on scalars (non numpy arrays). I'd like to avoid type-checking in ff_smart.

NNN
  • 697
  • 1
  • 5
  • 15
  • Sorry, I wasn't clear. It isn't a ```DivisionByZeroError``` that is thrown, it is a ```RuntimeWarning```. I tried promoting the warning to an exception but I'm not sure what your exact implementation is. It's not easy to paste the function definition in this comment. – NNN Jan 15 '22 at 10:10
  • So you are asking how to disable a runtime warning? – Patrick Artner Jan 15 '22 at 10:11
  • [why-cant-i-suppress-numpy-warnings](https://stackoverflow.com/questions/29347987/why-cant-i-suppress-numpy-warnings) ? – Patrick Artner Jan 15 '22 at 10:11
  • I don't want to suppress the warning - I want to "vectorize" ```ff_smart``` using numpy magic. – NNN Jan 15 '22 at 10:13
  • 1
    [best-way-to-implement-numpy-sinx-x-where-x-might-contain-0](https://stackoverflow.com/questions/36323003/best-way-to-implement-numpy-sinx-x-where-x-might-contain-0) – Patrick Artner Jan 15 '22 at 10:23
  • @PatrickArtner Thank you. Is there any other way, that is generalizable to other functions with such singularities? – NNN Jan 15 '22 at 10:29
  • No idea. You can mark your own post as dupe if that solves it for you. I would not want a magic "I can do all things and always well behave" function - garbage in=garbage (exception) out works for me. – Patrick Artner Jan 15 '22 at 10:33

2 Answers2

1

you can do:

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

If you want to use the power of numpy, a different answer, still useful to know is to use masked arrays:

# 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)
Neb
  • 2,270
  • 1
  • 12
  • 22
  • Yes, but that probably loses advantage of using numpy's fast C-code which probably could compute np.sin(x)/x in chunks instead of one at a time. I think there should be a better way. – NNN Jan 15 '22 at 10:04
  • @Nachiket I updated the answer using the numpy library. Please check it out and if it helped, accept it. – Neb Jan 15 '22 at 16:54
1

For conditional operations as you describe numpy has the numpy where function.

You can do

np.where(x==0, 1, np.sin(x)/x)
Mangochutney
  • 206
  • 2
  • 3