NumPy: Devuelve 0 con división por cero

Estoy tratando de realizar una división inteligente en Python, pero si se encuentra un cero, necesito que el cociente sea solo 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 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 obtener lo mejor de la numpy mientras configuro mi propia división por cero manejo de errores?

En numpy v1.7 +, puedes aprovechar la opción “dónde” para ufuncs . Puede hacer las 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 la división en cualquier lugar ‘donde’ b no es igual a cero. Cuando b es igual a cero, entonces permanece sin cambios respecto del valor que originalmente le asignó en el argumento ‘out’.

Aprovechando las otras respuestas, y mejorando en:

  • Manejo 0/0 agregando invalid='ignore' a numpy.errstate()
  • introduciendo numpy.nan_to_num() para convertir np.nan a 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)) 

Salida:

 c: [ 0. 0. 0. 1. 0.66666667] 

Sobre la base de la respuesta de @Franck Dernoncourt, arreglando -1 / 0:

 def div0( a, b ): """ ignore / 0, div0( [-1, 0, 1], 0 ) -> [0, 0, 0] """ with np.errstate(divide='ignore', invalid='ignore'): c = np.true_divide( a, b ) c[ ~ np.isfinite( c )] = 0 # -inf inf NaN return c div0( [-1, 0, 1], 0 ) array([0, 0, 0]) 

One-liner (advertencia de tiros)

 np.nan_to_num(array1 / array2) 

Intenta hacerlo en dos pasos. División primero, luego reemplazar.

 with numpy.errstate(divide='ignore'): result = numerator / denominator result[denominator == 0] = 0 

La línea numpy.errstate es opcional, y solo evita que numpy le informe sobre el “error” de dividir entre cero, ya que ya tiene la intención de hacerlo, y manejar ese caso.

También puede reemplazar basado en inf , solo si los tipos de matriz son flotantes, según esta respuesta :

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

Una respuesta que encontré buscando una pregunta relacionada fue manipular la salida en función de si el denominador era cero o no.

Supongamos que arrayA y arrayB se han inicializado, pero arrayB tiene algunos ceros. Podríamos hacer lo siguiente si queremos calcular arrayC = arrayA / arrayB forma segura.

En este caso, siempre que tengo una división por cero en una de las celdas, configuro la celda para que sea igual a myOwnValue , que en este caso sería cero

 myOwnValue = 0 arrayC = np.zeros(arrayA.shape()) indNonZeros = np.where(arrayB != 0) indZeros = np.where(arrayB = 0) # division in two steps: first with nonzero cells, and then zero cells arrayC[indNonZeros] = arrayA[indNonZeros] / arrayB[indNonZeros] arrayC[indZeros] = myOwnValue # Look at footnote 

Nota al pie: retrospectivamente, esta línea es innecesaria de todos modos, ya que arrayC[i] se arrayC[i] instancia a cero. Pero si fuera el caso de que myOwnValue != 0 , esta operación haría algo.

Otra solución que vale la pena mencionar:

 >>> a = np.array([1,2,3], dtype='float') >>> b = np.array([0,1,3], dtype='float') >>> b_inv = np.array([1/i if i!=0 else 0 for i in b]) >>> a*b_inv array([0., 2., 1.])