2016-04-10 12 views
0

Ich möchte eine Funktion gleichzeitig auf zwei entsprechende Elemente anwenden, ohne eine for-Schleife zu verwenden. Nehmen wir an, ich habe die folgenden zwei ndarrays x und y und eine Funktion foo, die in zwei 1d-Arrays einnimmt und die beta berechnet. Das Endergebnis ich will, ist beta00 = foo(x[0, 0],y[0]) zu berechnen, beta01 = foo(x[0, 1], y[1]), beta10 = foo(x[1, 0],y[0]), beta11 = foo(x[1, 1], y[1]) und ergeben ein erwartetes Ergebnis vonWenden Sie eine Funktion auf die entsprechenden Zeilen von zwei Arrays gleichzeitig an (ohne for-Schleife)

[[beta00, beta01], 
    [beta10, beta11]] 

Ich habe in vectorize Funktion suchen und anwenden Funktion, aber immer noch keine Lösung. Könnte mir jemand dabei helfen? Vielen Dank im Voraus.

import numpy as np 
x = np.array([[[0, 1, 2, 3], [0, 1, 2, 3]], 
       [[2,3,4,5], [2,3,4,5]]]) 
y = np.array([[-1, 0.2, 0.9, 2.1], [-1, 0.2, 0.9, 2.1]]) 

def foo(x,y): 
    A = np.vstack([x, np.ones(x.shape)]).T 
    return np.linalg.lstsq(A, y)[0][0] 
+0

Sie können Ihre foo als def foo neu definieren (x), wobei x wird ein Tupel und dann verwenden Sie map (foo, zip (x, y)) – Aquiles

+0

Ihr Code wird klarer, wenn Sie die gemeinsame 2d Numpy Indizierung verwenden, 'a [0,0]' anstelle von 'a [0] [ 0] '. Und 'x.shape [0]' anstatt 'len (x)'. Mit anderen Worten, machen Sie es sehr klar, wo Sie 1d, 2d, etc Arrays haben. Das heißt, der Schlüssel zur echten Vektorisierung ist das Schreiben von 'foo', so dass mehrdimensionale Arrays akzeptiert werden. – hpaulj

Antwort

1

So möchten Sie

beta[i,j] = foo(x[i,j,:], y[j,:]) 

Wo foo 2 1d Arrays nimmt und gibt einen Skalar. Die explizite : machen deutlich, dass wir 3 und 2 Arrays verwenden.

np.vectorize wird nicht helfen, da seine Funktion Skalare, nicht Arrays akzeptieren muss. Und - es ist keine Geschwindigkeitslösung. Es ist eine ebenso schöne Möglichkeit, Broadcasting zu ermöglichen, indem Eingaben mit einer Vielzahl von Dimensionen gehandhabt werden.

Es gibt Schleifen Wrapper wie apply_along(over)_axis, aber sie sind immer noch Python-Level-Schleifen. Der Schlüssel zu jeder echten Beschleunigung wird die foo Überarbeitung sein, so dass es auf 2 oder 3d Arrays funktioniert, nicht nur auf 1d. Aber das kann mehr Arbeit sein, als es wert ist, oder sogar unmöglich.

So Referenz muss jede Alternative entsprechen:

beta = np.zeros(x.shape[:2]) 
for i in range(x.shape[0]): 
    for j in range(x.shape[1]): 
     beta[i,j] = foo(x[i,j,:],y[j,:]) 

Eine alternative Möglichkeit, die mehrdimensionalen Indizes zu erzeugen, ist:

for i,j in np.ndindex(x.shape[:2]): 
    beta[i,j] = foo(x[i,j,:], y[j,:]) 

aber es ist nicht eine Zeitersparnis.

Blick in ob foo kann ein 2D-y,

foo(x[i,j,:], y[None,j,:]) 

Ziel schließlich in der Lage sein zu tun, um zu akzeptieren, geschrieben werden:

beta = foo1(x, y[None,:]) 
+0

Das macht Sinn. Vielen Dank. Aber nur um numpy zu lernen, wie soll ich 'apply_along (over) _axis' hier verwenden? Ich schaute auf den Arzt, aber ich bin immer noch ein wenig verwirrt. – no89key

+0

Ich habe Fragen zu den 'apply ...' Funktionen beantwortet, habe sie aber nicht für meinen eigenen Code verwendet. Sie passen möglicherweise nicht in diesen Fall, da sie so entworfen wurden, dass sie nur mit einem Eingabearray arbeiten und die Iteration nicht über 2 koordinieren. – hpaulj

Verwandte Themen