Week 1 – Python: Indexing

Sep 7, 2012 • Ben Waugh

Concept map

This took a while to create, partly because I spent some time experimenting with Inkscape and other drawing and diagramming applications before giving up and resorting to freehand drawing on paper, but also because I had never used Numpy before. So this is a concept map drawn not by a subject expert but a comparative novice. I did also find it attempting to mutate into some kind of UML-inspired collaboration diagram at some points, which I guess is not the same thing as a concept map.

Examples

I would like to think given more time I could come up with a better chosen pair of examples in the sense of a minimal pair that illustrates some relevant contrast, but these are all I have right now.

Mainstream

>>> import numpy as np
>>> b = np.ones((4,4))
>>> b
array([[ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.],
       [ 1.,  1.,  1.,  1.]])
>>> b[0:2,0:2] = 99.9
>>> b
array([[ 99.9,  99.9,   1. ,   1. ],
       [ 99.9,  99.9,   1. ,   1. ],
       [  1. ,   1. ,   1. ,   1. ],
       [  1. ,   1. ,   1. ,   1. ]])

While I would count this as mainstream, to understand the creation of the array b requires noticing that what is passed to ones() is a single argument which is a tuple representing the shape of the desired array, rather than two separate integer values. The assignment b[0:2,0:2] illustrates how slicing is used to address part of an array, and this reference can be used to assign to the array contents as well as to read them.

Boundary

>>> b[0:4,0]
array([ 99.9,  99.9,   1. ,   1. ])
>>> b[0,0:4]
array([ 99.9,  99.9,   1. ,   1. ])
>>> b[0:4,0] = -1.
>>> b[0,0:4] = -2.
>>> b
array([[ -2. ,  -2. ,  -2. ,  -2. ],
       [ -1. ,  99.9,   1. ,   1. ],
       [ -1. ,   1. ,   1. ,   1. ],
       [ -1. ,   1. ,   1. ,   1. ]])

This illustrates using mixed scalar and “slice” indices to refer to a lower-dimensional sub-array of a 2D array. Both b[0:4,0] and b[0,0:4] are 1D arrays with four elements, but the former refers to a column and the latter to a row. Only in two dimensions is there a distinction between a column and a row, and this corresponds to using slices in both indices

>>> b[0:4,0:1]
array([[-2.],
       [-1.],
       [-1.],
       [-1.]])

Deeper concepts and prerequisites

This section of the Software Carpentry course is a good illustration of encapsulation, in that complex tasks can be achieved faster and more reliably by dealing with high-level objects like arrays than by dealing with nested loops over primitive numeric data. My particular examples don’t really illustrate this aspect, but the latter in particular does touch on the difference between a 1D array and a 2D array with one dimension having unit size. I’m sure there is something interesting in there somewhere.

Prerequisites for this section are a familiarity with the mathematical concept of an array, and with the Python syntax for lists and for creating objects.

General comments

I would estimate it has taken my about 5 hours in total to read the relevant chapters of the book, watch the Software Carpentry lectures and make notes, draw the concept map, think of examples and write this blog post. This is more than I expected, but I have learned about Numpy as well as reflecting on the teaching principles involved

Some of the material in the Software Carpentry video did not work as expected, which probably indicates a dependency on the version of Numpy. Namely in the section on “Basic Operations”, the resize() method does not select a block of given rows and columns but flattens the data before reshaping it.