This guide will introduce you to the basics of NumPy array iteration. We will also have a deep dive into the iterator object nditer
and the powerful iteration capabilities it offers.
First, let’s look at iterating NumPy arrays without using the nditer
object.
Iterating a one-dimensional array is simple with the use of For
loop.
1A = np.arange(12)
2for cell in A:
3 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
The end
specifies the character that needs to be printed after printing the value. By default, it prints a new line character.
Similar to the programming languages like C# and Java, you can also use a while
loop to iterate the elements in an array. For example:
1i = 0
2while A[i] < A.size:
3 print(A[i])
4 i = i+1
5 if(i==A.size):
6 break
Output:
10
21
32
43
54
65
76
87
98
109
1110
1211
A.size
returns the number of elements in the array. Note the indented block after :
for while loop and the if statement that is required to pass the syntax check.
If you use the same syntax to iterate a two-dimensional array, you will only be able to iterate a row.
1A = np.arange(12).reshape(4,3)
2for row in A:
3 print(row)
Output:
1[0 1 2]
2[3 4 5]
3[6 7 8]
4[ 9 10 11]
To iterate each cell in the two-dimensional array, nest the for
loop.
1for row in A:
2 for cell in row:
3 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
If you do not want to write two for
loops, you can use the flatten
function that flattens the two-dimensional array into a one-dimensional array. For example:
1for cell in A.flatten():
2 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
NumPy provides a multi-dimensional iterator object called nditer
to iterate the elements of an array. For example, you can use nditer
in the previous example as:
1for cell in np.nditer(A):
2 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
You can control how the elements are accessed with nditer
using the order
parameter. If you specify the order as C
then C order is followed, which is traversing the elements in the array horizontally. If you specify the order as F,
the Fortran order is followed which is traversing the elements in the array vertically.
For example, to get the ‘C’ order:
1for cell in np.nditer(A, order='C'):
2 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
To get the Fortran order:
1for cell in np.nditer(A, order='F'):
2 print(cell, end=' ')
Output:
10 3 6 9 1 4 7 10 2 5 8 11
By default, nditer
follows the order ‘k’ which means that it follows an order to match the memory layout of the array. This default setting allows it to access the elements in the least possible time. To prove that, let’s define a matrix ‘B’ as the transpose of the two-dimensional matrix ‘A.’ So we have:
1A
Output:
1array([[ 0, 1, 2],
2 [ 3, 4, 5],
3 [ 6, 7, 8],
4 [ 9, 10, 11]])
And the transpose matrix ‘B’:
1B = A.T
2B
Output:
1array([[ 0, 3, 6, 9],
2 [ 1, 4, 7, 10],
3 [ 2, 5, 8, 11]])
So, if we iterate with the default order ‘k,’ we should see the same output for both the matrices ‘A’ and ‘B’.
1for cell in np.nditer(A):
2 print(cell, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
1for x in np.nditer(B):
2 print(x, end=' ')
Output:
10 1 2 3 4 5 6 7 8 9 10 11
Nditer
treats the elements of the array as read-only. So, if you try to modify the values, you will run into an error.
1for cell in np.nditer(A):
2 cell[...] =cell*2
Output:
1ValueError: assignment destination is read-only
To modify the array while you iterate, use the op_flags
parameter. So, to update the elements of the array:
1for cell in np.nditer(A, op_flags=['readwrite']):
2 cell[...] =cell*2
3A
Output:
1array([[ 0, 2, 4],
2 [ 6, 8, 10],
3 [12, 14, 16],
4 [18, 20, 22]])
To iterate two arrays simultaneously, pass two arrays to the nditer
object. Then you have array ‘A,’ a four by three two-dimensional array and an array ‘S,’ a one-dimensional array object:
1S = np.arange(3)
2S
Output:
1array([0, 1, 2])
So, to iterate the arrays ‘A’ and ‘S’ simultaneously:
1for a,s in np.nditer([A,S]):
2 print(a, s)
Output:
10 0
22 1
34 2
46 0
58 1
610 2
7…
This image summarizes how the iteration works across two arrays, ‘A’ and ‘S’:
If you would like to have a constant value from the matrix ‘S’ for each element in a row in the array ‘A,’ then use the following matrix ‘R’ with shape four by one:
1R = np.arange(4).reshape(4,1)
2R
Output:
1array([[0],
2 [1],
3 [2],
4 [3]])
1R.shape
Output:
1(4, 1)
1for a,r in np.nditer([A,R]):
2 print(a, r)
Output:
10 0
22 0
34 0
46 1
58 1
6...
This image summarizes the above operation:
Note that both the arrays need to follow the broadcasting rules if you need to iterate simultaneously on two different arrays. Review my previous guide on broadcasting in NumPy: Broadcasting NumPy Arrays for Arithmetic Operations.
The nditer
iterator object provides a systematic way to touch each of the elements of the array. This guide only gets you started with tools to iterate a NumPy array. In addition to the capabilities discussed in this guide, you can also perform more advanced iteration operations like Reduction Iteration, Outer Product Iteration, etc.