Numpy where and division by zero

后端 未结 5 1131
盖世英雄少女心
盖世英雄少女心 2020-12-04 01:00

I need to compute x in the following way (legacy code):

x = numpy.where(b == 0, a, 1/b) 

I suppose it worked in python-2.x (as

5条回答
  •  盖世英雄少女心
    2020-12-04 01:55

    A old trick for handling 0 elements in an array division is to add a conditional value:

    In [63]: 1/(b+(b==0))
    Out[63]: array([1.        , 1.        , 0.5       , 0.33333333])
    

    (I used this years ago in apl).


    x = numpy.where(b == 0, a, 1/b) is evaluated in the same way as any other Python function. Each function argument is evaluated, and the value passed to the where function. There's no 'short-circuiting' or other method of bypassing bad values of 1/b.

    So if 1/b returns a error you need to either change b so it doesn't do that, calculate it in context that traps traps the ZeroDivisionError, or skips the 1/b.

    In [53]: 1/0
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
     in ()
    ----> 1 1/0
    
    ZeroDivisionError: division by zero
    In [54]: 1.0/0
    ---------------------------------------------------------------------------
    ZeroDivisionError                         Traceback (most recent call last)
     in ()
    ----> 1 1.0/0
    
    ZeroDivisionError: float division by zero
    In [55]: 1/np.array(0)
    /usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
      #!/usr/bin/python3
    Out[55]: inf
    

    What are a and b? Scalars, arrays of some size?


    where makes most sense if b (and maybe a) is an array:

    In [59]: b = np.array([0,1,2,3])
    

    The bare division gives me a warning, and an inf element:

    In [60]: 1/b
    /usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
      #!/usr/bin/python3
    Out[60]: array([       inf, 1.        , 0.5       , 0.33333333])
    

    I could use where to replace that inf with something else, for example a nan:

    In [61]: np.where(b==0, np.nan, 1/b)
    /usr/local/bin/ipython3:1: RuntimeWarning: divide by zero encountered in true_divide
      #!/usr/bin/python3
    Out[61]: array([       nan, 1.        , 0.5       , 0.33333333])
    

    The warning can be silenced as @donkopotamus shows.

    An alternative to seterr is errstate in a with context:

    In [64]: with np.errstate(divide='ignore'):
        ...:     x = np.where(b==0, np.nan, 1/b)
        ...:     
    In [65]: x
    Out[65]: array([       nan, 1.        , 0.5       , 0.33333333])
    

    How to suppress the error message when dividing 0 by 0 using np.divide (alongside other floats)?

提交回复
热议问题