Iterating Arrays

import numpy as np

1D Arrays

a = np.arange(11)**2
a
array([  0,   1,   4,   9,  16,  25,  36,  49,  64,  81, 100])
# Iteratating over an array 
for i in a:
    print(i)
0
1
4
9
16
25
36
49
64
81
100
# Iteratating over an array 
for i in a:
    print(i * 2)
0
2
8
18
32
50
72
98
128
162
200

Multi-Dimensional Arrays

Iterating over multidimensional arrays is done with respect to the first axis:

students = np.array([['Alice','Beth','Cathy','Dorothy'],
                     [65,78,90,81],
                     [71,82,79,92]])

Each iteration will be over the rows of the array

for i in students:
    print('i = ', i)
i =  ['Alice' 'Beth' 'Cathy' 'Dorothy']
i =  ['65' '78' '90' '81']
i =  ['71' '82' '79' '92']

Flatten a multi-dimensional array

If one wants to perform an operation on each element in the array, one can use the flatten function which will flatten the array to a single dimension.
By default, the flattening will occur row-wise (also knows as C order)

for element in students.flatten():
    print(element)
Alice
Beth
Cathy
Dorothy
65
78
90
81
71
82
79
92

Fortran order flattening

To flatten a 2D array column-wise, use the Fortran order

for element in students.flatten(order='F'):
    print(element)
Alice
65
71
Beth
78
82
Cathy
90
79
Dorothy
81
92

nditer

Efficient multi-dimensional iterator object to iterate over arrays

x = np.arange(12).reshape(3,4)
x
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

Default iteration behavior is C order

This is row-wise iteration, similar to iterating over a C-order flattened array

for i in np.nditer(x):
    print(i)
0
1
2
3
4
5
6
7
8
9
10
11

Fortran order

This is like iterating over an array which has been flattened column-wise

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

Flags

There are a number of flags which we can pass as a list to nditer. Many of these involve setting buffering options
If we want iterate over each column, we can use the flag argument with value ‘external_loop’

for i in np.nditer(x, order = 'F', flags = ['external_loop']): 
    print(i)
[0 4 8]
[1 5 9]
[ 2  6 10]
[ 3  7 11]

Modifying Array Values

By default, the nditer treats the input array as a read-only object. To modify the array elements, you must specify either read-write or write-only mode. This is controlled with per-operand flags.

Writing on a read-only array results in an error

for arr in np.nditer(x):
    arr[...] = arr * arr
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-22-2dde0a500dd6> in <module>
      1 for arr in np.nditer(x):
----> 2     arr[...] = arr * arr

ValueError: assignment destination is read-only

We set the ops_flag to make the array read-write

for arr in np.nditer(x, op_flags = ['readwrite']):
    arr[...] = arr * arr
x
array([[  0,   1,   4,   9],
       [ 16,  25,  36,  49],
       [ 64,  81, 100, 121]])