web-dev-qa-db-fra.com

NumPy: Retour avec division par zéro

J'essaie de diviser les éléments en python, mais si un zéro est rencontré, le quotient doit être égal à zéro.

Par exemple:

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

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

Je pouvais toujours simplement utiliser une boucle for dans mes données, mais pour utiliser réellement les optimisations de numpy, j'ai besoin de la fonction divide pour renvoyer 0 sur les erreurs de division par zéro au lieu d'ignorer l'erreur.

Sauf si quelque chose me manque, il ne semble pas que numpy.seterr () puisse renvoyer des valeurs en cas d'erreur. Quelqu'un a-t-il d'autres suggestions sur la façon dont je pourrais tirer le meilleur parti de numpy tout en fixant ma propre division des erreurs de traitement des erreurs?

59
hlin117

Dans numpy v1.7 +, vous pouvez tirer parti de l'option "où" pour ufuncs . Vous pouvez faire les choses en une seule ligne et vous n'avez pas à traiter avec le gestionnaire de contexte 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]

Dans ce cas, le calcul de la division est effectué n'importe où 'où' b n'est pas égal à zéro. Lorsque b est égal à zéro, il reste inchangé par rapport à la valeur que vous avez initialement indiquée dans l'argument 'out'.

98
DStauffman

S'appuyant sur la réponse de @Franck Dernoncourt, corrigeant -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])
36
denis

En s'appuyant sur les autres réponses, et en améliorant:

Code:

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))

Sortie:

c: [ 0.          0.          0.          1.          0.66666667]
35
Franck Dernoncourt

One-Liner (avertissement)

np.nan_to_num(array1 / array2)
13
Ulf Aslak

Essayez de le faire en deux étapes. Division d'abord, puis remplacez.

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

La ligne numpy.errstate est facultative et empêche simplement numpy de vous informer de "l'erreur" de division par zéro, puisque vous avez déjà l'intention de le faire, et de gérer ce cas.

11
Pi Marillion

Vous pouvez également remplacer basé sur inf, uniquement si les types de tableau sont des flottants, comme indiqué dans cette réponse :

>>> 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.])
2
atomh33ls

Une autre solution à noter:

>>> 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.])
0
T. Gwen

Une réponse que j'ai trouvée en cherchant dans une question connexe était de manipuler la sortie en fonction du dénominateur ou non.

Supposons que arrayA et arrayB aient été initialisés, mais arrayB a des zéros. Nous pourrions faire ce qui suit si nous voulons calculer arrayC = arrayA / arrayB en toute sécurité.

Dans ce cas, chaque fois que j'ai une division par zéro dans l'une des cellules, je règle la cellule pour qu'elle soit égale à myOwnValue, ce qui dans ce cas serait zéro

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

Note de bas de page: Rétrospectivement, cette ligne est de toute façon inutile, puisque arrayC[i] est instancié à zéro. Mais si c'était le cas avec myOwnValue != 0, cette opération ferait quelque chose.

0
hlin117