2011-08-06 98 views
96

有沒有那麼詳細的替代方式:迭代一個numpy的陣列

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

我想出了這一點:

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

從而節省了一個缺口,但仍然是相當難看。

我希望的東西,看起來像這樣的僞代碼:

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

難道這樣的事情存在嗎?

回答

138

我認爲你正在尋找ndenumerate

>>> 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 

關於性能。它比列表理解慢一點。

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 

如果你擔心性能,你可以通過查看ndenumerate實施,這確實兩件事情,轉換到一個數組和循環進一步優化了一下。如果你知道你有一個數組,你可以調用平面迭代器的.coords屬性。

a = X.flat 
%timeit list([(a.coords, x) for x in a.flat]) 
1 loop, best of 3: 305 ms per loop 
+0

請注意這項工作,但速度慢得令人難以置信。你更好地手動迭代。 – Marty

35

如果你只需要索引,你可以嘗試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)] 
9

看到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 = 3是行不通的,使用y *= 0y += 3代替。

+0

或使用y [...] = 3 –