2016-10-21 2 views
2

Ich habe ein Array von Form (10, 100000) und eine Funktion f, die ein Array von Form (100000,) zu einem Array von Form (200,200) nimmt. Was ist der einfachste Weg, um f auf jede der 10 Zeilen anzuwenden, um ein Array von Form (10,200,200) zu erhalten? Ich hatte gehofft, apply_along_axis zu verwenden, aber es scheint, es wird nicht funktionieren, weil die Dimensionalität der Ausgabe von f höher ist als die Dimensionalität des Eingangs.Wie mache ich numpy apply_along_axis, wenn die Funktion ein höherdimensionales Array zurückgibt?

(Allgemeiner gegeben, ein Array a der Form (x1,...,xn,y1,...,ym) und Funktion f die (y1,...,ym) auf Arrays von (z1,...,zp) Form Arrays von Form annimmt, möchten Sie vielleicht f zu den letzten m Dimensionen a, für jede Einstellung des anzuwenden erste n Dimensionen von a, eine Reihe von Form (x1,...,xn,z1,...,zp) zu erhalten. Oder Sie können ein Problem haben, die einer dieser Form umgesetzt werden kann. Was ist der beste Weg, um Transformationen wie diese zu tun?)

+0

Vielleicht möchten Sie in ['np.nditer'] (https://docs.scipy.org/doc/numpy/reference/generated/numpy.nditer.html) schauen – Eric

+1

' np.ndindex' ist was Sie Notwendigkeit für eine partielle Iteration. – hpaulj

+0

Wenn ich richtig verstehe, diese Funktionen nur iterieren, so würde ich noch irgendwie manuell das Ergebnis aufbauen müssen, das ich will. Tatsächlich scheint der Iterationsteil selbst so zu sein, als wäre es mit For-Schleifen genauso einfach zu machen, und vielleicht wäre der resultierende Code für Leute, die nicht mit den Feinheiten von Numpy vertraut sind, vielleicht offensichtlicher? – gmr

Antwort

1

Mein erster Gedanke ist a umgestalten, kollabiert die erste n Dimensionen bis eins. Dann ist es nur eine Frage der Iteration über diese Dimension, wobei f auf jedes Unterfeld angewendet wird. Sammeln Sie die Ergebnisse in einer Liste (oder einem Array der richtigen Größe). Endlich umgestalten.

Wie Sie es beschreiben, sind die x1...xn Dimensionen nur für die Fahrt.

Schauen Sie sich den Code für apply_along_axis an. Es iteriert über alle Achsen mit Ausnahme desjenigen, der an die Funktion übergeben wird. Es macht nichts, was du mit deiner eigenen Iteration nicht so gut kannst. Es würde die Iteration über x1...xn verarbeiten, aber die y Dimensionen müssen auf 1 reduziert werden und erfordern eine Funktion, die die gleiche Form zurückgibt.

Der Kern dieser Funktion ist

res = func1d(arr[tuple(i.tolist())], *args, **kwargs) 
outarr[tuple(ind)] = res 

wo outarr hat auf die richtige Größe abgezeichnet sind, und ind wird über alle Abmessungen (mit einer Ausnahme) abgestuft. Es hat ein slice Objekt, wo die res geht.

=====================

Ein einfaches Beispiel mit einem Array 2D-Eingabestart:

In [933]: def foo(arr): 
    ...:  return arr.reshape(2,-1) 
    ...: 
In [934]: source=np.arange(12).reshape(3,4) 
In [935]: dest=np.zeros((source.shape[0],2,2),source.dtype) 
In [936]: for i,r in enumerate(source): 
    ...:  dest[i,...] = foo(r) 
    ...:  
In [937]: dest 
Out[937]: 
array([[[ 0, 1], 
     [ 2, 3]], 

     [[ 4, 5], 
     [ 6, 7]], 

     [[ 8, 9], 
     [10, 11]]]) 

so dass diese auf iteriert die Zeilen der Quelle, generiert neue Arrays und fügt sie an der richtigen Stelle des Ziels ein. Um das Ziel einzurichten, muss ich wissen was foo erzeugt (dimensionsmäßig).

Die Liste Anfügen Ansatz erfordert nicht, dass viel Wissen:

In [938]: dest=[] 
In [939]: for i,r in enumerate(source): 
    ...:  dest.append(foo(r))  
In [940]: dest 
Out[940]: 
[array([[0, 1], 
     [2, 3]]), array([[4, 5], 
     [6, 7]]), array([[ 8, 9], 
     [10, 11]])] 
In [941]: np.array(dest) 
... 

Es kommt auf die alte Frage: ‚Wie kann ich ein neues Array aus einer Funktion generieren?‘

Verwandte Themen