English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

NumPy Array Iteration

The NumPy iterator object numpy.nditer provides a flexible way to access one or more array elements.

The most basic task of an iterator is to access array elements.

Next, we use the arange() function to create a 2X3 array and iterate over it using nditer.

import numpy as np
a = np.arange(12).reshape(2,6)
print('The original array is:')
print(a)
print('\n')
print('Iterative output element:')
for x in np.nditer(a):
    print(x, end=" ")

Output result is:

Original array as follows:
[[ 0 1 2 3 4 5]
 [ 6 7 8 9 10 11]]
Iterative output of array elements as follows:
0 1 2 3 4 5 6 7 8 9 10 11

The order chosen in the above example is not standard C or Fortran order; it is consistent with the array's memory layout, which is done to improve access efficiency, with the default being row-major (row-major order, or C-order).

This reflects the default behavior of accessing each element without considering its specific order. We can see this by iterating over the transpose of the array and comparing it with the copy method that accesses the transpose of the array in C order, as shown in the following example:

import numpy as np
a = np.arange(12).reshape(2,6)
for x in np.nditer(a.T):
    print(x, end=" ")
print('\n')
for x in np.nditer(a.T.copy(order='C')):
    print(x, end=" ")

Output result is:

0 1 2 3 4 5 6 7 8 9 10 11 
0 6 1 7 2 8 3 9 4 10 5 11

From the above examples, it can be seen that the traversal order of a and a.T is the same, that is, their storage order in memory is also the same, but a.T.copy(order = 'C') The traversal results are different because it is different from the storage method of the first two, the default is row access.

Control the traversal order

for x in np.nditer(a, order='F'): Fortran order is column-major;for x in np.nditer(a.T, order='C'): C order is row-major;

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('The original array is:')
print(a)
print('\n')
print('The transpose of the original array is:')
b = a.T
print(b)
print('\n')
print('Sorted in the order of C style:')
c = b.copy(order='C')
print(c)
for x in np.nditer(c):
    print(x, end=" ")
print('\n')
print('Sorted in the order of F style:')
c = b.copy(order='F')
print(c)
for x in np.nditer(c):
    print(x, end=" ")

Output result is:

The original array is:
[[ 0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]]
The transpose of the original array is:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]]
Sorted in the order of C style:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]]
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95 
Sorted in the order of F style:
[[ 0 25 50 75]
 [ 5 30 55 80]
 [10 35 60 85]
 [15 40 65 90]
 [20 45 70 95]]
0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95

It is possible to explicitly set to force the nditer object to use a certain order:

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('The original array is:')
print(a)
print('\n')
print('Sorted in the order of C style:')
for x in np.nditer(a, order='C'):
    print(x, end=', ',)
print('\n')
print('Sorted in the order of F style:')
for x in np.nditer(a, order='F'):
    print(x, end=" ")

Output result is:

The original array is:
[[ 0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]]
Sorted in the order of C style:
0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 
Sorted in the order of F style:
0 25 50 75 5 30 55 80 10 35 60 85 15 40 65 90 20 45 70 95

Modify the value of elements in the array

The nditer object has another optional parameter op_flags. By default, nditer treats the array to be iterated as a read-only object (read-only), in order to modify the values of array elements while traversing the array, it is necessary to specify read-write or write-only mode.

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('The original array is:')
print(a)
print('\n')
for x in np.nditer(a, op_flags=['readwrite']):
    x[...]=2*x
print('The modified array is:')
print(a)

Output result is:

The original array is:
[[ 0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]]
The modified array is:
[[ 0 10 20 30 40]
 [ 50 60 70 80 90]
 [100 110 120 130 140]
 [150 160 170 180 190]]

Using an external loop

The constructor of the nditer class has a flags parameter, which can accept the following values:

ParameterDescription
c_indexIt can track the C ordered index
f_indexIt can track the Fortran ordered index
multi-indexEach iteration can track a type of index
external_loopThe given values are a one-dimensional array with multiple values, not a zero-dimensional array

In the following example, the iterator traverses the corresponding columns and combines them into a one-dimensional array.

import numpy as np
a = np.arange(0,100,5)
a = a.reshape(4,5)
print('The original array is:')
print(a)
print('\n')
print('The modified array is:')
for x in np.nditer(a, flags=['external_loop'], order='F'):
    print(x, end=" ")

Output result is:

The original array is:
[[ 0 5 10 15 20]
 [25 30 35 40 45]
 [50 55 60 65 70]
 [75 80 85 90 95]]
The modified array is:
[ 0 25 50 75]] [ 5 30 55 80] [10 35 60 85]] [15 40 65 90] [20 45 70 95]

Broadcast Iteration

If two arrays are broadcastable, the nditer combination object can iterate them simultaneously. Assuming the dimension of array a is 3X4, the dimension of array b is 1X4 If the use of the following iterator (array b is broadcast to the size of a).

import numpy as np
a = np.arange(0,60,5)
a = a.reshape(3,4)
print('The first array is:')
print(a)
print('\n')
print('The second array is:')
b = np.array([1, 2, 3, 4], dtype = int)
print(b)
print('\n')
print('Modified array is:')
for x, y in np.nditer([a, b]):
    print("%d:%d" % (x, y), end=" ")

Output result is:

The first array is:
[[ 0 5 10 15]
 [20 25 30 35]
 [40 45 50 55]]
The second array is:
[1 2 3 4]
Modified array is:
0:1, 5:2, 10:3, 15:4, 20:1, 25:2, 30:3, 35:4, 40:1, 45:2, 50:3, 55:4,