Verwenden von Numpy Vectorize auf Funktionen, die Vektoren zurückgeben

numpy.vectorize nimmt eine Funktion f: a-> b und wendet sie in g: a [] -> b [].

Das funktioniert gut, wenn a und b Skalare sind, aber ich kann nicht an einen Grund denken, warum es nicht mit b als ndarray oder liste arbeiten würde, dh f: a-> b [] und g: a [] -> B [] []

Beispielsweise:

 import numpy as np def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) g = np.vectorize(f, otypes=[np.ndarray]) a = np.arange(4) print(g(a)) 

Dies ergibt:

 array([[ 0. 0. 0. 0. 0.], [ 1. 1. 1. 1. 1.], [ 2. 2. 2. 2. 2.], [ 3. 3. 3. 3. 3.]], dtype=object) 

Ok, also gibt die richtigen Werte, aber die falschen dtype. Und noch schlimmer:

 g(a).shape 

Ergibt:

 (4,) 

Also ist dieses Array so ziemlich nutzlos. Ich weiß, ich kann es umwandeln:

 np.array(map(list, a), dtype=np.float32) 

Um mir zu geben was ich will

 array([[ 0., 0., 0., 0., 0.], [ 1., 1., 1., 1., 1.], [ 2., 2., 2., 2., 2.], [ 3., 3., 3., 3., 3.]], dtype=float32) 

Aber das ist weder effizient noch pythonisch. Kann jeder von euch einen saubereren Weg finden, dies zu tun?

Danke im Voraus!

4 Solutions collect form web for “Verwenden von Numpy Vectorize auf Funktionen, die Vektoren zurückgeben”

np.vectorize ist nur eine Bequemlichkeitsfunktion. Es macht eigentlich keinen Code schneller . Wenn es nicht bequem ist, np.vectorize zu benutzen, schreiben Sie einfach Ihre eigene Funktion, die wie Sie es wünschen.

Der Zweck von np.vectorize ist es, Funktionen zu verwandeln, die nicht numpy-aware sind (z. B. Floats als Input und Return Floats als Output) in Funktionen, die auf (und zurückgeben) numpy Arrays arbeiten können.

Ihre Funktion f ist schon numpy-aware – es verwendet ein numpy Array in seiner Definition und gibt ein numpy Array zurück. Also np.vectorize ist nicht eine gute Passform für Ihren Anwendungsfall.

Die Lösung ist also nur, um deine eigene Funktion zu rollen, die so funktioniert, wie du es wünschst.

 import numpy as np def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) g = np.vectorize(f, otypes=[np.ndarray]) a = np.arange(4) b = g(a) b = np.array(b.tolist()) print(b)#b.shape = (4,5) c = np.ones((2,3,4)) d = g(c) d = np.array(d.tolist()) print(d)#d.shape = (2,3,4,5) 

Dies sollte das Problem beheben und es wird funktionieren, unabhängig davon, welche Größe Ihre Eingabe ist. "Map" funktioniert nur für eine dimensionale eingänge. Mit ".tolist ()" und die Schaffung eines neuen ndarray löst das Problem mehr und nett (ich glaube). Hoffe das hilft.

Ich habe eine Funktion geschrieben, es passt zu deinem Bedarf.

 def amap(func, *args): '''array version of build-in map amap(function, sequence[, sequence, ...]) -> array Examples -------- >>> amap(lambda x: x**2, 1) array(1) >>> amap(lambda x: x**2, [1, 2]) array([1, 4]) >>> amap(lambda x,y: y**2 + x**2, 1, [1, 2]) array([2, 5]) >>> amap(lambda x: (x, x), 1) array([1, 1]) >>> amap(lambda x,y: [x**2, y**2], [1,2], [3,4]) array([[1, 9], [4, 16]]) ''' args = np.broadcast(None, *args) res = np.array([func(*arg[1:]) for arg in args]) shape = args.shape + res.shape[1:] return res.reshape(shape) 

Lassen Sie versuchen

 def f(x): return x * np.array([1,1,1,1,1], dtype=np.float32) amap(f, np.arange(4)) 

Ausgänge

 array([[ 0., 0., 0., 0., 0.], [ 1., 1., 1., 1., 1.], [ 2., 2., 2., 2., 2.], [ 3., 3., 3., 3., 3.]], dtype=float32) 

Sie können es auch mit Lambda oder teilweise für Bequemlichkeit wickeln

 g = lambda x:amap(f, x) g(np.arange(4)) 

Beachten Sie die docstring von vectorize sagt

Die vectorize Funktion wird vor allem für die Bequemlichkeit, nicht für die Leistung zur Verfügung gestellt. Die Implementierung ist im Wesentlichen eine for-Schleife.

So würden wir erwarten, dass die amap hier ähnliche Leistung wie amap haben. Ich habe es nicht überprüft.

Wenn die Aufführung wirklich wichtig ist, sollten Sie etwas anderes berücksichtigen, zB direkte Array-Berechnung mit reshape und broadcast , um Schleife in reiner Python zu vermeiden (beide amap und amap sind der spätere Fall).

Der beste Weg, dies zu lösen, wäre, ein 2-D-NumPy-Array (in diesem Fall ein Spalten-Array) als Eingabe für die ursprüngliche Funktion zu verwenden, die dann einen 2-D-Ausgang mit den Ergebnissen erzeugt, von denen ich glaube, dass du erwartet hast.

Hier ist, wie es im Code aussehen könnte:

 import numpy as np def f(x): return x*np.array([1, 1, 1, 1, 1], dtype=np.float32) a = np.arange(4).reshape((4, 1)) b = f(a) # b is a 2-D array with shape (4, 5) print(b) 

Dies ist eine viel einfachere und weniger fehleranfällige Möglichkeit, die Operation abzuschließen. Anstatt zu versuchen, die Funktion mit numpy.vectorize zu verwandeln, beruht diese Methode auf NumPys natürlicher Fähigkeit, Arrays zu senden. Der Trick besteht darin, sicherzustellen, dass mindestens eine Dimension eine gleiche Länge zwischen den Arrays hat.

  • Vectorisierung: Keine gültige Sammlung
  • Eine Funktion auf einem zweidimensionalen numpy Array zu senden
  • Numpy: finden Sie den euklidischen Abstand zwischen zwei 3-D-Arrays
  • Schnelles Berechnen von Eigenvektoren für jedes Element eines Arrays in Python
  • Vektoroperationen mit numpy
  • Ändern von etwas von Iteration über ein numpy Array zu Vektorisierung
  • Normalisierung eines numpy Arrays
  • Online-Version von scikit-Learn's TfidfVectorizer
  • Pandas: Umformung von Daten
  • Vektorisierung einer Numpy-Slice-Operation
  • Kovarianz mit Säulen
  • Python ist die beste Programmiersprache der Welt.