49

I have tried the following:

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
print a
rows = a.shape[0]
cols = a.shape[1]
print rows
print cols

for x in range(0, cols - 1):
    for y in range(0, rows -1):
        print a[x,y]

This only prints the numbers 1 through 6.

I have also tried only subtracting 1 from either rows or cols in the range, but that either leads to an out-of-bounds error or not all numbers being printed.

Kyle F Hartzenberg
  • 2,567
  • 3
  • 6
  • 24
CompSci-PVT
  • 1,303
  • 2
  • 10
  • 23

4 Answers4

106

You get prettier code with:

for iy, ix in np.ndindex(a.shape):
    print(a[iy, ix])

resulting in:

1
2
3
4
5
6
7
8
9
10
11
12
Markus Dutschke
  • 9,341
  • 4
  • 63
  • 58
  • 1
    I got one question: Is this the most efficient method for accessing a value at index ix,iy? I'm trying to implement an image processing algorithm that's why I'm asking for. Thanks! – Ali Ihsan Elmas Mar 23 '20 at 17:09
  • 1
    @Ali Ihsan Elmas: This is probably /surely not an efficient way for image processing. Use 'scipy.ndimage' and image filters instead. The functions 'convolve' and 'generic_filter' are interesting candidates to start with. – Markus Dutschke Mar 24 '20 at 09:50
  • 1
    Prefer the order `iy, ix` for images and other cases where the fastest changing axis is semantically "X", if you still want to understand what's really happening. – Christopher Bruns Nov 17 '21 at 17:07
  • 1
    @Christopher Bruns: you are right! I changed the arguments order in my answer to your proposal. Thank you – Markus Dutschke Nov 17 '21 at 19:05
35

a.shape[0] is the number of rows and the size of the first dimension, while a.shape[1] is the size of the second dimension. You need to write:

for x in range(0, rows):
    for y in range(0, cols):
        print a[x,y]

Note how rows and cols have been swapped in the range() function.

Edit: It has to be that way because an array can be rectangular (i.e. rows != cols). a.shape is the size of each dimension in the order they are indexed. Therefore if shape is (10, 5) when you write:

a[x, y]

the maximum x is 9 and the maximum y is 4. x and y are actually poor names for array indices because they do not represent cartesian coordinates, but a location in memory. You can use i and j instead:

for i in range(0, rows):
    for j in range(0, cols):
        print a[i,j]

The documentation is a bit long but has a good, in-depth description of indices and shapes.

Aiden Cullo
  • 312
  • 3
  • 15
fouronnes
  • 3,838
  • 23
  • 41
4

You can use xrange.

for x in xrange(rows):
    for y in xrange(cols):
        print a[x,y]
Avión
  • 7,963
  • 11
  • 64
  • 105
  • Thank you. Could you explain why using range(0, n) does not work? And what is the advantage to using xrange? Also, why does it seem that when iterating through x and y coordinates it is always opposite. X should be columns and y should be rows. – CompSci-PVT May 28 '15 at 07:29
  • 1
    `range` also works, but adding the `-1` at the end removes the last `column` item and the entire last `row`. `xrange` is usually better in terms of performance. If you want a entire explanation of when to use `xrange` or `range`, please read: http://stackoverflow.com/questions/135041/should-you-always-favor-xrange-over-range – Avión May 28 '15 at 07:31
  • 8
    xrange has been replaced by range in Python 3. – Tanya Branagan Aug 11 '18 at 22:18
1

You can use np.nditer.

it = np.nditer(a, flags=['multi_index'])
for x in it:
    print("{} {}".format(x, it.multi_index))

Reference: Iterating Over Arrays

LunaElf
  • 345
  • 3
  • 6