Introduction

66

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.

`1 2 3`

`A = np.arange(12) for cell in A: print(cell, end=' ')`

python

Output:

`1`

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

python

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:

`1 2 3 4 5 6`

`i = 0 while A[i] < A.size: print(A[i]) i = i+1 if(i==A.size): break`

python

Output:

`1 2 3 4 5 6 7 8 9 10 11 12`

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

python

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

`1 2 3`

`A = np.arange(12).reshape(4,3) for row in A: print(row)`

python

Output:

`1 2 3 4`

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

python

To iterate each cell in the two-dimensional array, nest the `for`

loop.

`1 2 3`

`for row in A: for cell in row: print(cell, end=' ')`

python

Output:

`1`

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

python

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:

`1 2`

`for cell in A.flatten(): print(cell, end=' ')`

python

Output:

`1`

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

python

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:

`1 2`

`for cell in np.nditer(A): print(cell, end=' ')`

python

Output:

`1`

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

python

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:

`1 2`

`for cell in np.nditer(A, order='C'): print(cell, end=' ')`

python

Output:

`1`

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

python

To get the Fortran order:

`1 2`

`for cell in np.nditer(A, order='F'): print(cell, end=' ')`

python

Output:

`1`

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

python

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:

`1`

`A`

python

Output:

`1 2 3 4`

`array([[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8], [ 9, 10, 11]])`

python

And the transpose matrix ‘B’:

`1 2`

`B = A.T B`

python

Output:

`1 2 3`

`array([[ 0, 3, 6, 9], [ 1, 4, 7, 10], [ 2, 5, 8, 11]])`

python

So, if we iterate with the default order ‘k,’ we should see the same output for both the matrices ‘A’ and ‘B’.

`1 2`

`for cell in np.nditer(A): print(cell, end=' ')`

python

Output:

`1`

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

python

`1 2`

`for x in np.nditer(B): print(x, end=' ')`

python

Output:

`1`

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

python

`Nditer`

treats the elements of the array as read-only. So, if you try to modify the values, you will run into an error.

`1 2`

`for cell in np.nditer(A): cell[...] =cell*2`

python

Output:

`1`

`ValueError: assignment destination is read-only`

python

To modify the array while you iterate, use the `op_flags`

parameter. So, to update the elements of the array:

`1 2 3`

`for cell in np.nditer(A, op_flags=['readwrite']): cell[...] =cell*2 A`

python

Output:

`1 2 3 4`

`array([[ 0, 2, 4], [ 6, 8, 10], [12, 14, 16], [18, 20, 22]])`

python

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:

`1 2`

`S = np.arange(3) S`

python

Output:

`1`

`array([0, 1, 2])`

python

So, to iterate the arrays ‘A’ and ‘S’ simultaneously:

`1 2`

`for a,s in np.nditer([A,S]): print(a, s)`

python

Output:

`1 2 3 4 5 6 7`

`0 0 2 1 4 2 6 0 8 1 10 2 …`

python

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:

`1 2`

`R = np.arange(4).reshape(4,1) R`

python

Output:

`1 2 3 4`

`array([[0], [1], [2], [3]])`

python

`1`

`R.shape`

python

Output:

`1`

`(4, 1)`

python

`1 2`

`for a,r in np.nditer([A,R]): print(a, r)`

python

Output:

`1 2 3 4 5 6`

`0 0 2 0 4 0 6 1 8 1 ...`

python

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.

66