2014-10-08 17 views
36

Ich versuche, eine elementweise Aufteilung in Python durchzuführen, aber wenn eine Null gefunden wird, muss der Quotient einfach Null sein.NumPy: Rückgabe 0 mit Division durch Null

Zum Beispiel:

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

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

konnte ich immer benutzen Sie einfach eine for-Schleife durch meine Daten, aber um wirklich numpy die Optimierungen nutzen, muss ich die Teilungsfunktion 0 auf divide zurück durch Null-Fehler statt sie zu ignorieren der Fehler.

Es sei denn, ich vermisse etwas, es scheint nicht numpy.seterr() kann Werte bei Fehlern zurückgeben. Hat jemand irgendwelche anderen Vorschläge, wie ich das Beste aus dem Numpigen herausholen könnte, während ich meine eigene Division durch Null-Fehlerbehandlung einstelle?

+0

In meiner Python-Version (Python 2.7.11 | Continuum Analytics, Inc.), die genau die Ausgabe, die Sie erhalten. Mit einer Warnung. –

+0

Die knappste richtige Antwort ist https://StackOverflow.com/a/37977222/2116338 – mrplants

Antwort

40

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

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

>>> 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 Divide-Berechnung überall durch, wo b nicht gleich Null ist. Wenn b gleich Null ist, bleibt es unverändert von dem Wert, den Sie ihm ursprünglich im Argument 'out' gegeben haben.

+0

Dies sollte die akzeptierte Antwort sein. – mrplants

+0

FWIW Ich mag auch Denis Antwort. Es wäre schön, alle Antworten in einem zusammenzufassen. – hlin117

10

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 Linie ist optional und verhindert nur numpy von Ihnen über die „Fehler“ erzählt von Null des Teilens, da Sie bereits sind die Absicht, dies zu tun, und dass die Sachbearbeitung.

+4

Sie sollten wahrscheinlich die Division im Kontext 'np.errstate (dividieren = 'ignorieren') durchführen:' –

+0

@WarrenWeckesser Fair Punkt. Ich habe die Antwort bearbeitet, um den Kontext einzubeziehen. 'dividieren = 'warnen' könnte auch nützlich sein, wenn er trotzdem benachrichtigt werden möchte. –

+0

funktioniert nicht, wenn "Nenner" skalar ist – denis

2

Sie können auch auf inf Basis ersetzen, nur, wenn die Array dtypes Schwimmer sind, wie pro this answer:

>>> 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.]) 
1

Eine Antwort fand ich eine weitere Frage der Suche war die Ausgabe zu manipulieren basierend darauf, ob der Nenner war Null oder nicht.

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

In diesem Fall, wenn ich eine Division durch Null in einer der Zellen haben, stelle ich die Zelle zu myOwnValue, die in diesem Fall wäre Null

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 gleich zu sein: Im Rückblick Diese Zeile ist sowieso unnötig, da arrayC[i] auf Null instanziiert wird. Aber wenn der Fall wäre, dass myOwnValue != 0, würde diese Operation etwas tun.

32

Aufbauend auf den anderen Antworten, und die Verbesserung 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)) 

Ausgang:

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

Guter Job für die Überprüfung '0/0' sowie '1/0' Fehler. – hlin117

35

Aufbauend auf @Franck Dernoncourt Antwort, Befestigungs -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]) 
+0

Danke, ich habe diesen Fehler mit @Frank Dernoncourts Code nicht einmal bemerkt. – hlin117

+0

Hallo, ich versuche Array-Mathe zu machen und ich möchte, dass 0/0 zu 0 führt, aber ich möchte auch np.NaN in meinen Berechnungen ignorieren. Wird das funktionieren? Außerdem versuche ich zu verstehen. Was macht c [~ np.isfinite (c)] = 0? Ich habe nie ~ in Python verwendet. Wofür ist das? Vielen Dank – user20408

+0

@ user20408, '~' invertiert 'True' und' False' in numply Arrays: 'print ~ np.array ([True, False, False])' '. 'c [~ np.isfinite (c)] = 0 'bedeutet: finde die Positionen, wo' c' endlich ist, invertiere diese zu NOT endlich mit '~', und setze die nicht endlichen Werte auf 0. Siehe auch http://stackoverflow.com/search?q=[numpy]+"boolean+indexing " – denis

10

One-Liner (wirft Warnung)

np.nan_to_num(array1/array2)