Индексация массивов#

import numpy as np

Индексация элементов#

Доступ к отдельному элементу массива осуществляется по его индексу:

# Случай одномерного массива
x = np.arange(10)
x[2]
np.int64(2)
# Всё так же, как и со списками и кортежами Python
x[-2]
np.int64(8)
# Преобразуем в двумерный массив
x.shape = 2, 5
x
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
# Случай двумерного массива
x[1, 3]
np.int64(8)
x[1, -1]
np.int64(9)

Important

Обратите внимание, что для доступа к элементу массива указывается столько индексов, какую размерность ndim имеет массив. В данном случае массив двумерный и его поле ndim = 2, поэтому указав два индекса, мы получили элемент. Если указать, например, три индекса, то получим ошибку. Если один - вернётся массив, соответствующий строке.

try:
    # Третий индекс лишний - нет такой оси
    print(x[1, 3, 2])
except IndexError as ex:
    # Получаем ошибку индексации
    # и соответствующее сообщение
    print(ex)
too many indices for array: array is 2-dimensional, but 3 were indexed
# Указываем меньшее число индексов -
# получаем, например, вторую строку
print(x[1])
[5 6 7 8 9]

Отметим следующее:

# Результат этого
x[0, 2]
np.int64(2)
# тот же, что и результат этого
x[0][2]
np.int64(2)

Однако второй вариант более медленный, поскольку создаётся промежуточный массив x[0], чего не происходит в первом случае.

Срезы и обходы#

a = np.arange(10)
# Срез от 2-го до 8-го элемента с шагом 2
a[1:7:2]
array([1, 3, 5])
# Срез от предпоследнего до 11-го элемента
a[-2:10]
array([8, 9])
# Срез от 3-го с конца до 4-го с начала
# с шагом -1 (в обратном направлении)
a[-3:3:-1]
array([7, 6, 5, 4])
# Срез с 6 элемента до конца
a[5:]
array([5, 6, 7, 8, 9])
# Срез можно получить, передав в качестве индекса
# список индексов
a[[1, 5, -1]]
array([1, 5, 9])

Срезы используются, чтобы, например, изменить несколько значений в массиве:

# Заменим каждый второй элемент -1,
# начиная со второго элемента (индекс 1)
a[1::2] = -1
a
array([ 0, -1,  2, -1,  4, -1,  6, -1,  8, -1])

Если есть матрица m, из которой требуется взять заданную строку или столбец, то это можно сделать так:

m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
m
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
# Берём вторую строку
m[1]
array([4, 5, 6])
# Берём первый столбец
# (как срез по всем строкам)
m[:, 0]
array([1, 4, 7])

Способы индексации размерностей#

Создадим трёхмерный массив:

x = np.array([[[1],[2],[3]], [[4],[5],[6]]])
x
array([[[1],
        [2],
        [3]],

       [[4],
        [5],
        [6]]])
x[..., 0]
array([[1, 2, 3],
       [4, 5, 6]])
# Это то же самое
x[:, :, 0]
array([[1, 2, 3],
       [4, 5, 6]])

Добавить в существующий массив новую ось единичной длины возможно с помощью np.newaxis:

x.shape
(2, 3, 1)
# Добавили новую ось как второй индекс
x[:, np.newaxis, :, :].shape
(2, 1, 3, 1)
# То же самое
x[:, None, :, :].shape
(2, 1, 3, 1)

См. также#

Более подробный гайд по индексации NumPy-массивов.