note.nkmk.me

NumPy: Slicing ndarray

Posted: 2020-09-26 / Tags: Python, NumPy

In Python, you can use slice [start:stop:step] to select a part of a sequence object such as a list, string, or tuple to get a value or assign another value.

It is also possible to select a subarray by slicing for the NumPy array numpy.ndarray and extract a value or assign another value.

This post describes the following:

  • Basics of slicing
  • Slice for one-dimensional numpy.ndarray
  • Slice for multi-dimensional numpy.ndarray
  • Views and copies
  • With fancy indexing

See the following post for how to extract rows and columns that satisfy the conditions.

Sponsored Link

Basics of slicing

In Python, you can use slice [start:stop:step] to select a part of a sequence object such as a list, string, or tuple to get a value or assign another value.

import numpy as np

l = list(range(10))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(l[4:8])
# [4, 5, 6, 7]

print(l[-5:-2])
# [5, 6, 7]

print(l[::-1])
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Slicing is a standard feature in Python. See the following post for details.

Slice for one-dimensional numpy.ndarray

Get a subarray

The slice for the one-dimensional numpy.ndarray is the same as the basic Python slice as in the example above.

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

print(a[4:8])
# [4 5 6 7]

print(a[-5:-2])
# [5 6 7]

print(a[::-1])
# [9 8 7 6 5 4 3 2 1 0]

Assign another value

The behavior of assignment using slices is different for list and for numpy.ndarray.

See the following post for assignment to list by slice. The number of elements selected by slice and the number of elements to be assigned do not have to match.

In numpy.ndarray, the value on the right side is converted by broadcasting and assigned.

If the right side is a scalar value, all elements selected by the slice will be replaced with that scalar value. If the right side is a one-dimensional array, it will be replaced with that array.

a[3:6] = 100
print(a)
# [  0   1   2 100 100 100   6   7   8   9]

a[3:6] = [100, 200, 300]
print(a)
# [  0   1   2 100 200 300   6   7   8   9]

When assigning an array, if the number of elements in the array to be assigned and the number of elements selected in the slice do not match, ValueError will occur.

# a[3:6] = [100, 200, 300, 400]
# ValueError: cannot copy sequence with size 4 to array axis with dimension 3

The same applies to slices for which step is specified.

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

print(a[2:8:2])
# [2 4 6]

a[2:8:2] = 100
print(a)
# [  0   1 100   3 100   5 100   7   8   9]

a[2:8:2] = [100, 200, 300]
print(a)
# [  0   1 100   3 200   5 300   7   8   9]

Slice for multi-dimensional numpy.ndarray

For multi-dimensional numpy.ndarray, slices of each dimension can be specified separated by commas.

Take the following two-dimensional array as an example.

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

Get a subarray

Specify slices for each dimension separated by commas.

print(a[1:, 1:3])
# [[ 5  6]
#  [ 9 10]]

Select rows

You can select rows using :. In this case, the trailing : can be omitted.

print(a[1:, :])
# [[ 4  5  6  7]
#  [ 8  9 10 11]]

print(a[1:])
# [[ 4  5  6  7]
#  [ 8  9 10 11]]

When selecting one row, if you specify the index by the scalar value instead of the slice, it will be selected as a one-dimensional array, but if you select one row by the slice, it will be selected as a two-dimensional array.

print(a[1])
# [4 5 6 7]

print(a[1].shape)
# (4,)

print(a[1:2])
# [[4 5 6 7]]

print(a[1:2].shape)
# (1, 4)

Be careful in cases that shape is important, such as matrix operations.

Select columns

The same applies to column selection. In this case, the first : cannot be omitted.

print(a[:, 1:3])
# [[ 1  2]
#  [ 5  6]
#  [ 9 10]]
print(a[:, 1])
# [1 5 9]

print(a[:, 1].shape)
# (3,)

print(a[:, 1:2])
# [[1]
#  [5]
#  [9]]

print(a[:, 1:2].shape)
# (3, 1)

You can use ... if : repeats. See the followint post.

Assign another value

As in the case of one-dimensional numpy.ndarray, in the assignment to the multi-dimensional numpy.ndarray, the value on the right side is converted by broadcasting and assigned.

When assigning an array, an ValueError will occur if the number of elements of the array to be assigned and the number of corresponding elements selected by the slice do not match.

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

print(a[1:, 1:3])
# [[ 5  6]
#  [ 9 10]]

a[1:, 1:3] = 100
print(a)
# [[  0   1   2   3]
#  [  4 100 100   7]
#  [  8 100 100  11]]

a[1:, 1:3] = [100, 200]
print(a)
# [[  0   1   2   3]
#  [  4 100 200   7]
#  [  8 100 200  11]]

a[1:, 1:3] = [[100, 200], [300, 400]]
print(a)
# [[  0   1   2   3]
#  [  4 100 200   7]
#  [  8 300 400  11]]

The same applies to slices for which step is specified.

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

print(a[1:, ::2])
# [[ 4  6]
#  [ 8 10]]

a[1:, ::2] = 100
print(a)
# [[  0   1   2   3]
#  [100   5 100   7]
#  [100   9 100  11]]

a[1:, ::2] = [100, 200]
print(a)
# [[  0   1   2   3]
#  [100   5 200   7]
#  [100   9 200  11]]

a[1:, ::2] = [[100, 200], [300, 400]]
print(a)
# [[  0   1   2   3]
#  [100   5 200   7]
#  [300   9 400  11]]
Sponsored Link

Views and copies

The subarray extracted by slicing is a view of the original array, and changing the elements of the sub-array also changes the elements of the original array.

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

a_slice = a[1:, 1:3]
print(a_slice)
# [[ 5  6]
#  [ 9 10]]

a_slice[0, 0] = 100
print(a_slice)
# [[100   6]
#  [  9  10]]

print(a)
# [[  0   1   2   3]
#  [  4 100   6   7]
#  [  8   9  10  11]]

You can make a copy of a subarray using copy(). Changing the elements of the copy does not change the elements of the original array.

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

a_slice_copy = a[1:, 1:3].copy()
print(a_slice_copy)
# [[ 5  6]
#  [ 9 10]]

a_slice_copy[0, 0] = 100
print(a_slice_copy)
# [[100   6]
#  [  9  10]]

print(a)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

See the following post for more information on views and copies in numpy.ndarray.

With fancy indexing

In NumPy, you can select a subarray from numpy.ndarray by a list of indexes.

Subarrays can be selected by combining fancy indexing and slicing.

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

print(a[[0, 2], 1:3])
# [[ 1  2]
#  [ 9 10]]
a[[0, 2], 1:3] = 100
print(a)
# [[  0 100 100   3]
#  [  4   5   6   7]
#  [  8 100 100  11]]

a[[0, 2], 1:3] = [100, 200]
print(a)
# [[  0 100 200   3]
#  [  4   5   6   7]
#  [  8 100 200  11]]

a[[0, 2], 1:3] = [[100, 200], [300, 400]]
print(a)
# [[  0 100 200   3]
#  [  4   5   6   7]
#  [  8 300 400  11]]

Note that the subarray extracted by fancy indexing is a copy, not a view.

a_subset = a[[0, 2], 1:3]
print(a_subset)
# [[100 200]
#  [300 400]]

a_subset[0, 0] = -1
print(a_subset)
# [[ -1 200]
#  [300 400]]

print(a)
# [[  0 100 200   3]
#  [  4   5   6   7]
#  [  8 300 400  11]]
Sponsored Link
Share

Related Categories

Related Posts