Pluralsight Logo
Author avatar

Ravikiran Srinivasulu

Author badge Author

Iterating Numpy Arrays

Ravikiran Srinivasulu

Author BadgeAuthor
  • Nov 12, 2018
  • 6 Min read
  • 27 Views
  • Nov 12, 2018
  • 6 Min read
  • 27 Views
Numpy
Python

Introduction

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.

Iterating NumPy Arrays

First, let’s look at iterating NumPy arrays without using the nditer object.

Iterating a One-dimensional Array

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=' ')

Output:

1
0 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:

1
2
3
4
5
6
i = 0
while A[i] < A.size:
    print(A[i])
    i = i+1
    if(i==A.size):
        break

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

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.

Iterating a Two-dimensional Array

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)

Output:

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

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=' ')

Output:

1
0 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:

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

Output:

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

A Look at the Nditer Object

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=' ')

Output:

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

Nditer Iteration Order

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.

memoryorder

For example, to get the ‘C’ order:

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

Output:

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

To get the Fortran order:

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

Output:

1
0 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:

1
A

Output:

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

And the transpose matrix ‘B’:

1
2
B = A.T
B

Output:

1
2
3
array([[ 0,  3,  6,  9],
       [ 1,  4,  7, 10],
       [ 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’.

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

Output:

1
0 1 2 3 4 5 6 7 8 9 10 11
1
2
for x in np.nditer(B):
    print(x, end=' ')

Output:

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

Modifying NumPy Arrays

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

Output:

1
ValueError: 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:

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

Output:

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

Iterating Two Arrays Simultaneously

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

Output:

1
array([0, 1, 2])

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

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

Output:

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

This image summarizes how the iteration works across two arrays, ‘A’ and ‘S’:

matrixS

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

Output:

1
2
3
4
array([[0],
       [1],
       [2],
       [3]])
1
R.shape

Output:

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

Output:

1
2
3
4
5
6
0 0
2 0
4 0
6 1
8 1
...

This image summarizes the above operation:

matrixR

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.

Conclusion

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.

1