Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
498 views
in Technique[技术] by (71.8m points)

python - shallow iteration with nditer

I've got such an array:

>>>y = np.random.randint(0, 255, (2,2,3))
>>>array([[[242, 14, 211],
           [198,  7,   0]],

          [[235,  60,  81],
           [164,  64, 236]]])

And I have to iterate over each triplet element (unfortunately vectorization won't help me here...). So I tried:

for i, j in np.nditer(y):
print y[i, j],

hoping I'd get such an output:

[242, 14, 211], [198, 7, 0], [235, 60, 81], [164, 64, 236], but no luck!

I get the error:

Traceback (most recent call last):

  File "<ipython-input-21-a336ef837a8a>", line 1, in <module>
    for i, j in np.nditer(y):    print y[i,j]

TypeError: iteration over a 0-d array

I'm quite sure I'm making a very obvious error... can anyone please help me?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Or reshape y

for i in y.reshape(-1,3):
    print i

A double iteration also works:

for x in y:
    for z in x:
        print z

Plain nditer iterates over each element of y (nditer does not give you the indices):

for i in np.nditer(y):
    print i   
    # wrong y[i]

You'll need to dig more into the flags and documentation for nditer to iterate over 2 of its dimensions. While nditer gives access to the underlying iteration mechanism, you don't usually need to use it - unless you are doing something unusual, or trying to speed up code with cython.


Here's an example of getting 2 values from iteration on an nditer object. There is one value for each array in the op list. Both x and z are () shape arrays.

for x,z in np.nditer([y,y]):
    print x,z

There's more on the use of nditer at http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html


This doc page has an example using external_loop that dishes out the array in subarrays, rather than individually. I can accomplish the same with the 3d y by reordering its axes:

y3=y.swapaxes(2,0).copy(order='C')
for i in np.nditer(y3,order='F',flags=['external_loop']):
    print i,

[242  14 211] [198   7   0] [235  60  81] [164  64 236]

So we can use nditer to do this shallow iteration, but is it worth it?


In Iterating over first d axes of numpy array, I stumbled upon ndindex:

for i in np.ndindex(y.shape[:2]):
    print y[i],
# [242  14 211] [198   7   0] [235  60  81] [164  64 236]

ndindex uses nditer. The trick to generating shallow iteration is to use a subarray using just the dimensions you want to iterate over.

class ndindex(object):
    def __init__(self, *shape):
        ...
        x = as_strided(_nx.zeros(1), shape=shape, strides=_nx.zeros_like(shape))
        self._it = _nx.nditer(x, flags=['multi_index', 'zerosize_ok'], order='C')
    def __next__(self):
        next(self._it)
        return self._it.multi_index

Or stripping out the essential parts of ndindex I get:

xx = np.zeros(y.shape[:2])
it = np.nditer(xx,flags=['multi_index'])                               
while not it.finished:
    print y[it.multi_index],
    it.iternext()
# [242  14 211] [198   7   0] [235  60  81] [164  64 236]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...