Fork me on GitHub

Python Array Indexing/Slicing

Jake Steinberg (28 July 2014)

This is meant to highlight differences in indexing methods/techniques between Python and MATLAB. I came upon this problem while attempting to pull out a 2-D array from within a larger 2-D array

To begin let's create an array for manipulation

In [22]:
import numpy as np
A = np.random.randint(0,51, size=(5,6))
A
Out[22]:
array([[18, 41, 16, 20,  0, 40],
       [10, 24, 38, 42, 24,  8],
       [28,  7,  7, 18, 36,  5],
       [36, 47, 23, 38,  0, 40],
       [49, 18, 19, 11,  7, 36]])

This array could represent a bathymetry file (spatially defined depth values), an image (pixel values), or any dataset. I would now like to define a new array (B) as a subset of array A. I would like to define B as rows 1:2 and columns 2:4 of array A. The following is a correct method to do so.

In [25]:
B = np.copy(A[1:3,2:5])
print B
[[38 42 24]
 [ 7 18 36]]

Remember that the last indexed value (row or column in this case) is not included (i.e. row 3 and column 5 are not included). Here the colon implies that I want rows one through 3 (exclusive) and columns 2 through 5 (exclusive). Now if instead I were to use commas to represent the rows and columns I would like to select, a different operation would be executed.

In [28]:
B1 = np.copy(A[[1,2,3],[2,3,4]])
print B1
[38 18  0]

Here the indexes provided are treated as coordinate points and thus three values are pulled from A and defined as B1. In MATLAB, this is not the case and the values would be treated as rows and columns! Note that the coordinate points must be provided as pairs. Where B was defined I pulled a different amount of rows than columns...here if you attempted the same an error would be returned. Another acceptable form is:

In [61]:
B2 = np.copy(A[1:3,[1,4]])
print B2
[[24 24]
 [ 7 36]]

Additional Properties

Let's create a 1-D array

In [39]:
x = np.array([1,3,6,8,7,2,9,0])
print x
[1 3 6 8 7 2 9 0]

In [50]:
a = x[3:]
b = x[0:6:2]
c = x[-3:8]
print a
print b
print c
[8 7 2 9 0]
[1 6 7]
[2 9 0]

Methods for Indexing and Slicing Arrays

In [35]:
index1,index2 = np.nonzero((A>=10) & (A<30))
print A

print index1 
print index2
[[18 41 16 20  0 40]
 [10 24 38 42 24  8]
 [28  7  7 18 36  5]
 [36 47 23 38  0 40]
 [49 18 19 11  7 36]]
[0 0 0 1 1 1 2 2 3 4 4 4]
[0 2 3 0 1 4 0 3 2 1 2 3]

The output of the numpy command nonzero is a tuple of arrays providing pairs of coordinates within A where the input argument is true (i.e. position (0,0) contains a value greater than 10 and less than 30).

In [57]:
index3 = np.logical_and(A>=10,A<=30)
print index3
[[ True False  True  True False False]
 [ True  True False False  True False]
 [ True False False  True False False]
 [False False  True False False False]
 [False  True  True  True False False]]

This output is an array equal in size to A. It returns true/false values where the input argument is satisfied or violated.

In [55]:
C1 = np.copy(A[index3])  
print C1
[18 16 20 10 24 24 28 18 23 18 19 11]

Returns an array of the desired values. But does not include their indices (as does np.nonzero)

Comments