NumPy - indexing and slicing

https://numpy.org/doc/stable/user/basics.indexing.html

https://numpy.org/doc/stable/reference/arrays.indexing.html

INTRODUCTION

Array indexing refers to any use of the square brackets ([]) to index array values.

Attention: Whereas slicings on lists and tuples create new objects, a slicing operation on an array creates a view on the original array.

If the number of objects in the selection tuple is less than the dimension N, then : is assumed for any subsequent dimensions.


a = np.arange(10)   # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

# Indexing: a[0] first, a[1] second, a[-1] last
# General syntax for slicing: a[start:stop], a[start:stop:step]
# Note that stop is not included.

a[2:5], a[:3], a[4:], a[::2] (even), a[1::2] (odd), a[::3]

# Exercise: negative start/stop/step, a[::-1] (reversed)

b = np.arange(12).reshape((3,4))
# array([[ 0,  1,  2,  3],
#        [ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]])

# Indexing: b[1][2] or b[1,2] gives 6.
# b[1][2] is less efficient, because a new temporary array is created!

b[1]   # the same as b[1,:]
# array([4, 5, 6, 7]), it is a view

# Slicing
b[:2,2:]
# array([[2, 3],
#        [6, 7]]) top right

b[1:,:]
# array([[ 4,  5,  6,  7],
#        [ 8,  9, 10, 11]]) bottom part

b[:,3:]
# array([[ 3],
#        [ 7],
#        [11]]) right part

b[::2,::3]
# array([[ 0,  3],
#        [ 8, 11]])

b[:,1]   # array([1, 5, 9]), shape=(3,)
b[1,:]   # array([4, 5, 6, 7]), shape=(4,)

# Exercise: only even/odd indexes, a sparse sample (every k)

c = np.arange(24).reshape((2,3,4))
# Indexing: c[1,2,3] or c[1][2,3] or c[1,2][3] or c[1][2][3] gives 23.
# c[1,2,3] is the most efficient.
# Slicing
c[:1,1:]   # equivalent to c[:1,1:,:]
c[:1]   # equivalent to c[:1,:,:]

a = np.arange(10)   # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
b = a[2:6]   # array([2, 3, 4, 5]) this is a view!
b[0] = 22
b[1] = 23
print(a)   # array([ 0,  1, 22, 23,  4,  5,  6,  7,  8,  9])
np.may_share_memory(a, b)   # True

c = a.reshape((2, 5))
np.may_share_memory(a, c)   # True

# Check if array owns it's data.
print(a.base)   # None, 'a' owns data
print(b.base)   # [ 0  1 22 23  4  5  6  7  8  9], 'a' is the base of 'b'

FILTERING ARRAYS

NumPy arrays may be indexed with other arrays (index arrays). For all cases of index arrays, what is returned is a copy of the original data, not a view as one gets for slices.


a = np.array( [20, 30, 40, 50] )

a > 35   # array([False, False,  True,  True])
a[a > 35]   # array([40, 50]), selecting items
# Boolean arrays are "mask" index arrays.

a[ np.array([1, 1, 3, 3, -2]) ]   # array([30, 30, 50, 50, 40])
# Index array is of integer type here. Negative values are permitted.

a[ np.array([[1, 1], [2, 3]]) ]
# array([[30, 30],
#        [40, 50]])

b = np.arange(10).reshape(2, 5)
# array([[0, 1, 2, 3, 4],
#        [5, 6, 7, 8, 9]])

b % 2 == 0
# array([[ True, False,  True, False,  True],
#        [False,  True, False,  True, False]])

b[b % 2 == 0]   # array([0, 2, 4, 6, 8]) even numbers, shape (5,)

b[b % 2 == 0] += 100   # selected items are changed in b!
# array([[100,   1, 102,   3, 104],
#        [  5, 106,   7, 108,   9]])

c = np.arange(35).reshape(5,7)
# 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, 32, 33, 34]])

c[ np.array([0,2,4]), np.array([0,1,2]) ]
# array([ 0, 15, 30])
# Selected items are c[0,0], c[2,1], c[4,2].

c[ np.array([0,2,4]), 1 ]   # broadcasting
# array([ 1, 15, 29])
# The same as c[ np.array([0,2,4]), np.array([1,1,1]) ]
# Selected items are c[0,1], c[2,1], c[4,1].

c[ np.array([0,2,4]) ]
# The same as c[ np.array([0,2,4]), : ].
# Index arrays may be combined with slices.
# array([[ 0,  1,  2,  3,  4,  5,  6],
#        [14, 15, 16, 17, 18, 19, 20],
#        [28, 29, 30, 31, 32, 33, 34]])

c[ c > 20 ]   # the result is a 1-D array
# array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34])

# Structural indexing tools.
c.shape                   # (5, 7)
c[:,np.newaxis,:].shape   # (5, 1, 7)
# There are no new elements in the array,
# just that the dimensionality is increased.