Thursday, May 24, 2012

NumPy Array Indexing

Extracting values from and inserting values into a Python list object is intuitive and powerful

This post demonstrates how to access elements of a Python list object. Once this concept is understood for a list, it can be easily extended to multi dimensioned NumPy arrays in a straight forward manner.

Let us first generate a one dimensioned NumPy array containing 11 elements, with values starting from 0 upto 10 at increment of 1. This is quite easily done using the range() function:
>>x = range(0, 10)
>>type(x)
list
>>x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

The list x has 10 elements, indexed from 0 to 9. Accessing any element of x requires you to know the index of the element. x returns the value of the initial element, namely 0. The following for loop prints the values of the elements in x:

>>for i in range(0, 10):
print x[i],
0 1 2 3 4 5 6 7 8 9

The same goes for insertion:
>>for i in range(0, 10):
x[i] = i * 2
print x[i],
0 2 4 6 8 10 12 14 16 18

Of course, you could access any element you wish.
>>x
2
>>x
8

Python allows indexing from the end of the list. The index of the last element is -1. Thus, x[-1] accesses the last element with the value 9. The index of the initial element, counted from the end of the array is -10, hence x[-10] returns the value of the initial element.
>>x = range(0, 10)
>>x[-1]
9
>>x[-10]
0
>>for i in range(-1, -11, -1):
print x[i],
9 8 7 6 5 4 3 2 1 0

In addition to accessing individual elements of a list, it is possible to access a range of elements. To return a list containing the first three elements of x, the syntax is:
>>y = x[0:3]
>>type(y)
list
>>y
[0, 1, 2]
Note that the object y is of type list. Further, the notation 0:3 means starting from 0, up to but not including, 3. Thus the values returned are from x to x, namely, 0, 1 and 2. See if you find what the following expressions will return:
>>x[-3:-1]
[7, 8]
>>x[2:5]
[2, 3, 4]
>>x[0:10:2]
[0, 2, 4, 6, 8]
>>x[1:10:2]
[1, 3, 5,7, 9]
While specifying a range of indices, it is possible to specify the step increment as shown the last two expressions above, which print out the values of the even numbered and odd numbered elements.

It is also possible to leave out one or more of the start and end indices if they happen to be the first or the last. It is possible to leave out the increment if it is 1. Thus x[:] is the same as x.
>>x[:]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>x[5:]
[5, 6, 7, 8, 9]
>>x[:5]
[0, 1, 2, 3, 4]
>>x[:-1]
[0, 1, 2, 3, 4, 5, 6, 7, 8]
>>x[-1::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>x[::]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>x[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Insertion works in a similar way, as long as the object on the right hand side matches that on the left hand side:
>>x[0:2] = [10, 20]
>>x
[10, 20, 2, 3, 4, 5, 6, 7, 8, 9]
The above syntax for extraction, when used on the left hand side does insertion.

The exact syntax will work with a NumPy array. You can test it out by replacing the command that generates the list with the command that generates a NumPy array, namely:
>>import numpy
>>x = numpy.array(range(0, 10))

In fact, this will work with the other Python container object, tuple.