2015-02-13 4 views
6

Warum kann ich ein ndarray nicht mit einer Liste von Tuple-Indizes wie dies indizieren?Indizieren eines numpy Arrays mit einer Liste von Tupeln

idx = [(x1, y1), ... (xn, yn)] 
X[idx] 

Stattdessen habe ich etwas unhandlich wie

idx2 = numpy.array(idx) 
X[idx2[:, 0], idx2[:, 1]] # or more generally: 
X[tuple(numpy.vsplit(idx2.T, 1)[0])] 

Gibt es eine einfachere, pythonic Art und Weise zu tun?

Antwort

13

Sie können eine Liste von Tupeln verwenden, aber die Konvention unterscheidet sich von dem, was Sie wollen. numpy erwartet eine Liste von Zeilenindizes, gefolgt von einer Liste von Spaltenwerten. Sie möchten anscheinend eine Liste von (x, y) Paaren angeben.

http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#integer-array-indexing Der relevante Abschnitt in der Dokumentation ist 'Integer Array Indizierung'.


Hier ist ein Beispiel, suchen 3 Punkte in einem 2D-Array. (2 Punkte in 2d können verwirrend sein):

In [223]: idx 
Out[223]: [(0, 1, 1), (2, 3, 0)] 
In [224]: X[idx] 
Out[224]: array([2, 7, 4]) 

Arbeiten mit dem Stil der xy-Paare von Indizes:

In [230]: idx1 = [(0,2),(1,3),(1,0)] 
In [231]: [X[i] for i in idx1] 
Out[231]: [2, 7, 4] 

In [240]: X[tuple(np.array(idx1).T)] 
Out[240]: array([2, 7, 4]) 

X[tuple(zip(*idx1))] ist ein weiterer Weg, um die Konvertierung zu tun. Die tuple() ist optional in Python2. zip(*...) ist ein Python-Idiom, das die Verschachtelung einer Liste von Listen umkehrt.

Sie sind auf dem richtigen Weg mit:

In [242]: idx2=np.array(idx1) 
In [243]: X[idx2[:,0], idx2[:,1]] 
Out[243]: array([2, 7, 4]) 

Mein tuple() ist nur ein bisschen kompakte (und nicht unbedingt mehr ‚pythonic‘). Angesichts der numpy Konvention ist eine Art von Konvertierung notwendig.

(Sollten wir überprüfen, was mit n-Dimensionen und m-Punkten funktioniert?)