Iterieren über ein numpy Array

135

Gibt es eine weniger ausführliche Alternative dazu:

for x in xrange(array.shape[0]):
    for y in xrange(array.shape[1]):
        do_stuff(x, y)

Ich habe mir das ausgedacht:

for x, y in itertools.product(map(xrange, array.shape)):
    do_stuff(x, y)

Das spart eine Einrückung, ist aber immer noch ziemlich hässlich.

Ich hoffe auf etwas, das wie dieser Pseudocode aussieht:

for x, y in array.indices:
    do_stuff(x, y)

Gibt es so etwas?

Ram Rachum
quelle
Ich bin in Python 2.7 und verwende Ihre Lösung mit den itertools. Ich habe in den Kommentaren gelesen, dass die Verwendung von itertools schneller sein wird. Allerdings (vielleicht weil ich in 2.7 bin) musste ich auch die Karte in der for-Schleife entpacken. for x, y in itertools.product(*map(xrange, array.shape)):
ALM
Es gibt eine Seite in der NumPy-Referenz mit dem Namen "Iterieren über Arrays": docs.scipy.org/doc/numpy/reference/arrays.nditer.html
Casey
Verwandte: stackoverflow.com/questions/29493183/…
Eulenfuchswiesel

Antworten:

187

Ich denke, Sie suchen die Zahl .

>>> a =numpy.array([[1,2],[3,4],[5,6]])
>>> for (x,y), value in numpy.ndenumerate(a):
...  print x,y
... 
0 0
0 1
1 0
1 1
2 0
2 1

In Bezug auf die Leistung. Es ist etwas langsamer als ein Listenverständnis.

X = np.zeros((100, 100, 100))

%timeit list([((i,j,k), X[i,j,k]) for i in range(X.shape[0]) for j in range(X.shape[1]) for k in range(X.shape[2])])
1 loop, best of 3: 376 ms per loop

%timeit list(np.ndenumerate(X))
1 loop, best of 3: 570 ms per loop

Wenn Sie sich Sorgen über die Leistung machen, können Sie ein wenig weiter optimieren, indem Sie sich die Implementierung von ansehen ndenumerate, die zwei Dinge bewirkt: Konvertieren in ein Array und Schleifen. Wenn Sie wissen, dass Sie ein Array haben, können Sie das .coordsAttribut des flachen Iterators aufrufen .

a = X.flat
%timeit list([(a.coords, x) for x in a.flat])
1 loop, best of 3: 305 ms per loop
SiggyF
quelle
1
Beachten Sie, dass dies funktioniert, aber unglaublich langsam ist. Sie sollten besser manuell iterieren.
Marty
43

Wenn Sie nur die Indizes benötigen, können Sie Folgendes versuchen numpy.ndindex:

>>> a = numpy.arange(9).reshape(3, 3)
>>> [(x, y) for x, y in numpy.ndindex(a.shape)]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
senderle
quelle
15

siehe nditer

import numpy as np
Y = np.array([3,4,5,6])
for y in np.nditer(Y, op_flags=['readwrite']):
    y += 3

Y == np.array([6, 7, 8, 9])

y = 3würde nicht funktionieren, verwenden y *= 0und y += 3stattdessen.

C19
quelle
2
oder benutze y [...] = 3
Donald Hobson