2017-03-11 5 views
0

Ich habe zwei Eingabe numpy Arrays mit jeweils Breiten- und Längenkoordinaten einer Reihe von Punkten: lats und lons.Numpy: Funktion auf zwei numply Arrays anwenden und zwei numpy Arrays zurückgeben

Ich habe eine Funktion geerbt, die jedes (lat,lon) Paar in ein (E,N) Paar wandelt:

def convert(lat,lon): #takes two floats as arguments (unit: degrees) 
    ... 
    computation #Actual function is too long to post 
    ... 
    return N,E #returns two floats (unit: meters) 

Meine Frage: wie könnte ich die gleiche Funktion gleichzeitig auf beiden Eingängen numpy Arrays effizient anwenden?

I der Modifizierung der Funktion dachte so, dass es eine Liste zurückgibt:

return [N,E] 

in einer solchen Art und Weise, dass:

rows = int(lat.shape[0]) #lat and lon have the same shape 
cols = int(lat.shape[1]) 
easting=numpy.zeros(shape=(rows,cols)) 
northing=numpy.zeros(shape=(rows,cols)) 
for i in range(0, rows): 
    for j in range(0, cols): 
     northing=convert(lon[i][j])[0] #first element of the returned list 
     easting=convert(lat[i][j])[1] #second element of the returned list 

Ich habe noch nicht diese getestet, aber es bei der Suche Ich fühle mich nicht sehr wohl, das wird funktionieren. Alle Einsichten werden sehr geschätzt.

+0

Dieses auf die Details der 'convert' Funktion abhängen. Es könnte im wörtlichen Sinne schon so funktionieren, wie Sie es wollen, oder Sie müssen Dinge wie 'math.sin' in' np.sin' umwandeln, oder es könnte im Grunde unmöglich sein, es effizient zu machen, wenn der Code auf APIs angewiesen ist Steuere oder ersetze nicht, dass jeweils ein Elementpaar benötigt wird. – user2357112

Antwort

1

definieren wir eine triviale Umwandlungs

def convert(lat, lon): 
    return lat*np.pi/180, lon*np.pi/180 

frompyfunc ist eine nützliche Methode ‚Skalar‘ -Funktion auf Arrays anzuwenden; Wir können haben es sogar in zwei Reihen übernehmen, und das Rück 2-Arrays (in einem Tupel)

In [233]: f = np.frompyfunc(convert,2,2) 
In [234]: lats=np.linspace(-45,45,5) 
In [235]: lons=np.linspace(0,100,5) 
In [236]: out = f(lats, lons) 
In [237]: out 
Out[237]: 
(array([-0.7853981633974483, -0.39269908169872414, 0.0, 0.39269908169872414, 
     0.7853981633974483], dtype=object), 
array([0.0, 0.4363323129985824, 0.8726646259971648, 1.3089969389957472, 
     1.7453292519943295], dtype=object)) 

Ein Merkmal ist, dass es ein Objekt Array zurückgibt, während Sie wahrscheinlich eine Float-Array wollen:

In [238]: out[0].astype(float) 
Out[238]: array([-0.78539816, -0.39269908, 0.  , 0.39269908, 0.78539816]) 

Oder mit auspacken:

In [239]: rlat, rlon = f(lats, lons) 
In [240]: rlat.astype(float) 
Out[240]: array([-0.78539816, -0.39269908, 0.  , 0.39269908, 0.78539816]) 

frompyfunc wird über die Eingänge laufen. In anderen Tests ist es tendenziell 2x schneller als explizitere Schleifen. Und in diesem Fall, da es ein Tupel zurückgibt, müssen Sie es nicht zweimal aufrufen, um 2 Ergebnisse zu erhalten.

Wie geschrieben, diese convert funktioniert genauso gut mit Arrays wie Skalare, so

In [241]: convert(lats, lons) 
Out[241]: 
(array([-0.78539816, -0.39269908, 0.  , 0.39269908, 0.78539816]), 
array([ 0.  , 0.43633231, 0.87266463, 1.30899694, 1.74532925])) 

, die viel schneller als jede Version sein wird, die in Python-Schleifen.

Also für echte Geschwindigkeit möchten Sie convert direkt mit Arrays arbeiten. Aber wenn es das nicht kann, dann ist frompyfunc eine bescheidene Verbesserung gegenüber Do-it-yourself-Schleifen.

Ein weiterer Vorteil frompyfunc - es gilt Array Rundfunk, wie in

f(lats[:,None], lons[None,:])