numpy und Teilen durch Null
Verfasst: Sonntag 25. Juli 2021, 11:33
Ich habe eine Menge von eindimensionalen arrays (Vektoren), die alle die Länge n + 1 haben. Könnte so etwas sein wie "zurückgelegter Weg", "Entfernung vom Endpunkt", "Zeit übrig", usw.
Die Länge ergibt sich aus der Erzeugung, der Speicherung und der Weiterverarbeitung dieser Vektoren. Manche dieser Vektoren haben als letzte Stelle immer 0 (alles andere ergibt inhaltlich keinen Sinn). Nun muss ich manchmal zwei dieser Vektoren dividieren, wobei beide Vektoren an der letzten Stelle eine 0 haben. Am sinnvollsten wäre es, wenn das Ergebnis an der letzten Stelle auch eine 0 hätte.
Gibt es da best practices oder so dafür? Ich habe folgende Varianten ausprobiert, wobei die erste ein RuntimeWarning ausspuckt, was nicht akzeptabel ist (kann man bestimmt irgendwie unterdrücken?):
(Bei der 1. Variante könnte/müsste man noch den letzten Wert durch 0 ersetzen, je nach Geschmack - da bin ich mir noch nicht sicher.)
%timeit liefert, dass die erste Variante die schnellste ist, es folgt die zweite, und die numpy-Funktionen sind am langsamsten.
Ich tendiere zur 2. Variante, aber die erste Variante mit Unterdrückung der Fehlermeldung an genau dieser Stelle könnte ich mir auch vorstellen. Aber vielleicht ist es ganz anders noch besser?
Die Länge ergibt sich aus der Erzeugung, der Speicherung und der Weiterverarbeitung dieser Vektoren. Manche dieser Vektoren haben als letzte Stelle immer 0 (alles andere ergibt inhaltlich keinen Sinn). Nun muss ich manchmal zwei dieser Vektoren dividieren, wobei beide Vektoren an der letzten Stelle eine 0 haben. Am sinnvollsten wäre es, wenn das Ergebnis an der letzten Stelle auch eine 0 hätte.
Gibt es da best practices oder so dafür? Ich habe folgende Varianten ausprobiert, wobei die erste ein RuntimeWarning ausspuckt, was nicht akzeptabel ist (kann man bestimmt irgendwie unterdrücken?):
Code: Alles auswählen
import numpy as np
n = 5
a = np.array([3, 3, 3, 2, 1, 0], dtype=float)
b = np.array([5, 4, 3, 2, 1, 0], dtype=float)
# 1. naiv
c = a / b
print(c)
# [0.6 0.75 1. 1. 1. nan]
# RuntimeWarning: invalid value encountered in true_divide
# 2. nur die letzte Stelle nicht teilen, in zero-array hinein
c = np.zeros(n + 1)
c[:-1] = a[:-1] / b[:-1]
print(c)
# [0.6 0.75 1. 1. 1. 0. ]
# 3. nur die letzte Stelle nicht teilen, Null anhängen
c = np.append(a[:-1] / b[:-1], 0.0)
print(c)
# [0.6 0.75 1. 1. 1. 0. ]
# 4. Oder nie durch Nullen teilen, in zero-array hinein
c = np.divide(a, b, out=np.zeros(n + 1), where=b != 0.0)
print(c)
# [0.6 0.75 1. 1. 1. 0. ]
%timeit liefert, dass die erste Variante die schnellste ist, es folgt die zweite, und die numpy-Funktionen sind am langsamsten.
Code: Alles auswählen
In [31]: %timeit a / b
<magic-timeit>:1: RuntimeWarning: invalid value encountered in true_divide
1.85 µs ± 231 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [32]: %%timeit
...: c = np.zeros(n + 1)
...: c[:-1] = a[:-1] / b[:-1]
3.02 µs ± 453 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [33]: %timeit c = np.append(a[:-1] / b[:-1], 0.0)
6.68 µs ± 304 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [34]: %timeit c = np.divide(a, b, out=np.zeros(n + 1), where=b != 0)
4.29 µs ± 230 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)