web-dev-qa-db-de.com

NumPy: Rückkehr mit Division durch Null

Ich versuche, eine elementweise Unterteilung in Python durchzuführen, aber wenn eine Null angetroffen wird, muss der Quotient nur Null sein.

Zum Beispiel:

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

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

Ich könnte immer nur eine for-Schleife durch meine Daten verwenden, aber um die Optimierungen von numpy wirklich nutzen zu können, brauche ich die Divide-Funktion, um bei Division durch Null Fehler 0 zurückzugeben, anstatt den Fehler zu ignorieren.

Wenn mir nicht etwas fehlt, scheint numpy.seterr () bei Fehlern keine Werte zurückzugeben. Hat jemand andere Vorschläge, wie ich das Beste aus Numpy herausholen kann, während ich meine eigene Division durch Null-Fehlerbehandlung setze?

59
hlin117

In numpy v1.7 + können Sie die Option "wo" für ufuncs nutzen. Sie können Dinge in einer Zeile erledigen, und Sie müssen sich nicht mit dem Kontextmanager für fehlerhafte Zustände befassen.

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

In diesem Fall führt es die Teilungsberechnung überall aus, wo 'b' nicht gleich Null ist. Wenn b gleich Null ist, bleibt es unverändert von dem Wert, den Sie ursprünglich im Argument "out" angegeben haben.

98
DStauffman

Aufbauend auf der Antwort von @Franck Dernoncourt, -1/0 korrigierend:

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

Auf den anderen Antworten aufbauen und verbessern auf:

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

Ausgabe:

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

Einliner (wirft eine Warnung)

np.nan_to_num(array1 / array2)
13
Ulf Aslak

Versuchen Sie es in zwei Schritten. Division zuerst, dann ersetzen.

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

Die numpy.errstate-Zeile ist optional und verhindert, dass numpy Sie über den "Fehler" der Division durch Null informiert, da Sie dies bereits vorhaben und diesen Fall bearbeiten.

11
Pi Marillion

Sie können auch basierend auf inf ersetzen, nur wenn die Array-Datentypen Floats sind, gemäß diese Antwort

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

Eine andere erwähnenswerte Lösung:

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

Eine Antwort, die ich bei der Suche nach einer verwandten Frage gefunden habe, war die Manipulation der Ausgabe basierend darauf, ob der Nenner Null war oder nicht.

Angenommen, arrayA und arrayB wurden initialisiert, arrayB hat jedoch einige Nullen. Wir könnten Folgendes tun, wenn wir arrayC = arrayA / arrayB sicher berechnen möchten.

Wenn ich in einer der Zellen eine Division durch Null habe, stelle ich in diesem Fall die Zelle auf myOwnValue ein, die in diesem Fall gleich Null wäre

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

Fußnote: Im Nachhinein ist diese Zeile ohnehin unnötig, da arrayC[i] zu Null instanziiert wird. Wenn jedoch myOwnValue != 0 wäre, würde diese Operation etwas unternehmen.

0
hlin117