Cómo devolver 0 con división por cero

Resuelto hlin117 asked hace 9 años • 9 respuestas

Estoy tratando de realizar una división por elementos en Python, pero si se encuentra un cero, necesito que el cociente sea simplemente cero.

Por ejemplo:

array1 = np.array([0, 1, 2])
array2 = np.array([0, 1, 1])

array1 / array2 # should be np.array([0, 1, 2])

Siempre podría usar un bucle for a través de mis datos, pero para utilizar realmente las optimizaciones de numpy, necesito que la función de división devuelva 0 al dividir por cero los errores en lugar de ignorar el error.

A menos que me esté perdiendo algo, no parece que numpy.seterr() pueda devolver valores en caso de errores. ¿Alguien tiene alguna otra sugerencia sobre cómo podría aprovechar al máximo numpy mientras configuro mi propio manejo de errores de división por cero?

hlin117 avatar Oct 08 '14 10:10 hlin117
Aceptado

En numpy v1.7+, puedes aprovechar la opción "dónde" para ufuncs . Puede hacer cosas en una línea y no tiene que lidiar con el administrador de contexto errstate.

>>> a = np.array([-1, 0, 1, 2, 3], dtype=float)
>>> b = np.array([ 0, 0, 0, 2, 2], dtype=float)

# If you don't pass `out` the indices where (b == 0) will be uninitialized!
>>> c = np.divide(a, b, out=np.zeros_like(a), where=b!=0)
>>> print(c)
[ 0.   0.   0.   1.   1.5]

En este caso, realiza el cálculo de división en cualquier lugar "donde" b no sea igual a cero. Cuando b es igual a cero, permanece sin cambios con respecto al valor que le dio originalmente en el argumento 'out'.

DStauffman avatar Jun 22 '2016 20:06 DStauffman

Aprovechando la respuesta de @Franck Dernoncourt, arreglando -1/0 y mi error en los escalares:

def div0( a, b, fill=np.nan ):
    """ a / b, divide by 0 -> `fill`
        div0( [-1, 0, 1], 0, fill=np.nan) -> [nan nan nan]
        div0( 1, 0, fill=np.inf ) -> inf
    """
    with np.errstate(divide='ignore', invalid='ignore'):
        c = np.true_divide( a, b )
    if np.isscalar( c ):
        return c if np.isfinite( c ) \
            else fill
    else:
        c[ ~ np.isfinite( c )] = fill
        return c
denis avatar Feb 29 '2016 09:02 denis

Aprovechando las otras respuestas y mejorando:

  • 0/0manipulación añadiendo invalid='ignore'anumpy.errstate()
  • introduciendo numpy.nan_to_num()para convertir np.nana 0.

Código:

import numpy as np

a = np.array([0,0,1,1,2], dtype='float')
b = np.array([0,1,0,1,3], dtype='float')

with np.errstate(divide='ignore', invalid='ignore'):
    c = np.true_divide(a,b)
    c[c == np.inf] = 0
    c = np.nan_to_num(c)

print('c: {0}'.format(c))

Producción:

c: [ 0.          0.          0.          1.          0.66666667]
Franck Dernoncourt avatar Aug 19 '2015 22:08 Franck Dernoncourt

DESPRECADO (SOLUCIÓN PYTHON 2):

Una sola línea (lanza advertencia)

np.nan_to_num(array1 / array2)
Ulf Aslak avatar Oct 13 '2016 13:10 Ulf Aslak