Indexing and Slicing

1-D array

1-D NumPy Array elements can be accessed by index, using syntax identical to Python lists: array[index] for a single element, or array[start:end] for a slice, where start and end are the starting and ending indexes for the slice.

arr = np.arange(10)

arr
# array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr[5]
# 5

arr[-1]
# 9

arr[5:8]
# array([5, 6, 7])

arr[:3]
# array([0, 1, 2])

arr[-3:]
# array([7, 8, 9])

# ndarray slicing is shallow copy
arr[5:8] = 12
arr
# array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])

# assign new variable to ndarray slicing is still 
# shallow copy
arr_slice = arr[5:8]
arr_slice[1] = 12345
arr
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])

Notice that when we select multiple elements, we get an array.

2-D Array

Nested Arrays can be accessed by adding additional comma-separated parameters.

arr2d = np.array([[1, 2, 3], 
                  [4, 5, 6], 
                  [7, 8, 9]])
arr2d[2]
# array([7, 8, 9])

arr2d[0, 2]
# 3

arr2d[:2, 1:]
# array([[2, 3],[5, 6]])

arr2d[1, :2]
# array([4, 5])

arr2d[:, :1]
# array([[1],[4],[7]])

Note that when we work with arrays that have more than one dimension, the relationship between the interior arrays is defined in terms of axes. A two-dimensional array has two axes: axis 0 represents the values that share the same indexical position (are in the same column), and axis 1 represents the values that share an array (are in the same row). This is illustrated below.

Boolean Indexing

NumPy elements can be indexed using conditionals. The syntax to filter an array using a conditional is array_name[conditional].

The returned array will contain only the elements for which the conditional evaluates to True.

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 
                  'Will', 'Joe', 'Joe'])
data = randn(7, 4)
names
# array(['Bob', 'Joe', 'Will', 'Bob', 
#        'Will', 'Joe', 'Joe'], dtype='|S4')
data
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [ 2.1452, 0.8799, -0.0523, 0.0672],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

names == 'Bob'
# array([True, False, False, True, 
#        False, False, False], dtype=bool)

data[names == 'Bob']
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [2.1452, 0.8799, -0.0523, 0.0672]])

data[names == 'Bob', 2:]
# array([[-0.2349, 1.2792],
#        [-0.0523, 0.0672]])

data[names == 'Bob', 3]
# array([ 1.2792, 0.0672])

data[-(names == 'Bob')]
# array([[-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

data[names != 'Bob']
# array([[-0.268 , 0.5465, 0.0939, -2.0445],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [-1.0023, -0.1698, 1.1503, 1.7289],
#        [ 0.1913, 0.4544, 0.4519, 0.5535],
#        [ 0.5994, 0.8174, -0.9297, -1.2564]])

# use & (and) and | (or) for more than one comparision
data[(names == 'Bob') | (names == 'Will')]
# array([[-0.048 , 0.5433, -0.2349, 1.2792],
#        [-0.047 , -2.026 , 0.7719, 0.3103],
#        [ 2.1452, 0.8799, -0.0523, 0.0672],
#        [-1.0023, -0.1698, 1.1503, 1.7289]])

Fancy Indexing

Fancy indexing is a term adopted by NumPy to describe indexing using integer arrays. Passing multiple index arrays does something slightly different; it selects a 1D array of elements corresponding to each tuple of indices:

arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i
arr
# array([[ 0., 0., 0., 0.],
#        [ 1., 1., 1., 1.],
#        [ 2., 2., 2., 2.],
#        [ 3., 3., 3., 3.],
#        [ 4., 4., 4., 4.],
#        [ 5., 5., 5., 5.],
#        [ 6., 6., 6., 6.],
#        [ 7., 7., 7., 7.]])

arr[[4, 3, 0, 6]]
# array([[ 4., 4., 4., 4.],
#        [ 3., 3., 3., 3.],
#        [ 0., 0., 0., 0.],
#        [ 6., 6., 6., 6.]])

# Using negative indices select rows from the end
arr[[-3, -5, -7]]
# array([[ 5., 5., 5., 5.],
#        [ 3., 3., 3., 3.],
#        [ 1., 1., 1., 1.]])

# create 1-dimension then reshape
arr = np.arange(32).reshape((8, 4))
# array([[ 0, 1, 2, 3],
#        [ 4, 5, 6, 7],
#        [ 8, 9, 10, 11],
#        [12, 13, 14, 15],
#        [16, 17, 18, 19],
#        [20, 21, 22, 23],
#        [24, 25, 26, 27],
#        [28, 29, 30, 31]])

arr[[1, 5, 7, 2], [0, 3, 1, 2]]
# array([ 4, 23, 29, 10])

arr[[1, 5, 7, 2]][:, [0, 3, 1, 2]]
# array([[ 4, 7, 5, 6],
# [20, 23, 21, 22],
# [28, 31, 29, 30],
# [ 8, 11, 9, 10]])

arr[np.ix_([1, 5, 7, 2], [0, 3, 1, 2])]
# array([[ 4, 7, 5, 6],
# [20, 23, 21, 22],
# [28, 31, 29, 30],
# [ 8, 11, 9, 10]])

Last updated

Was this helpful?