# 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.

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

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

## 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 article 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 article 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 following article.

### 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]]
``````

## 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 article 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]]
``````