Индексы и срезы
Чтобы работать с частью данных — строкой таблицы, столбцом, куском массива, — numpy даёт мощные способы индексации. Они похожи на срезы списков, но умеют больше.
Одномерный массив
Индексы и срезы работают как у списков:
import numpy as np
a = np.array([5, 8, 2, 9, 4, 7])
print(a[0], a[-1]) # 5 7
print(a[1:4]) # [8 2 9]
print(a[::2]) # [5 2 4] — каждый второй
print(a[::-1]) # [7 4 9 2 8 5] — наоборот
Таблица: индекс через запятую
В двумерном массиве индексы по осям пишутся через запятую в одних скобках:
m = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
print(m[2, 1]) # 10 — строка 2, столбец 1
print(m[0]) # [1 2 3 4] — вся строка 0
print(m[:, 3]) # [ 4 8 12] — весь столбец 3
Двоеточие : означает «всё по этой оси». Запись m[2][1] тоже работает, но m[2, 1] — правильный стиль numpy и быстрее.
Срез таблицы — прямоугольник
Срезы по обеим осям вырезают прямоугольный кусок:
print(m[0:2, 1:3])
# [[2 3]
# [6 7]]
print(m[1:, ::2]) # строки с 1-й, столбцы через один
# [[ 5 7]
# [ 9 11]]
Как и в Python, правая граница среза не входит. Если в задаче строки нумеруются с единицы и обе границы включены, отрезок с r1 по r2 — это срез r1 - 1 : r2.
Срез — это окно, а не копия
Важное отличие от списков: срез массива не копирует данные, а смотрит в тот же участок памяти:
a = np.arange(5) # [0 1 2 3 4]
part = a[1:4]
part[:] = 0 # обнулили «кусок»
print(a) # [0 0 0 0 4] — исходный массив тоже изменился
Это экономит память на больших данных. Если нужна независимая копия — a[1:4].copy().
Срезом можно и присваивать:
m[:, 0] = 0 # обнулить первый столбец
m[1] = [7, 7, 7, 7] # заменить строку
Выбор по списку индексов
Если в скобки передать список или массив индексов, numpy соберёт элементы с этими позициями в указанном порядке:
colors = np.array(["red", "green", "blue", "black"])
print(colors[[2, 0, 2]]) # ['blue' 'red' 'blue']
idx = np.array([3, 1])
print(colors[idx]) # ['black' 'green']
Это называется fancy indexing. В отличие от среза, результат — новый массив (копия). Индексы могут повторяться и идти в любом порядке — поэтому так удобно переставлять элементы.
Для таблиц можно выбирать строки списком: m[[2, 0]] — строки 2 и 0, или конкретные клетки парами списков: m[[0, 2], [1, 3]] — элементы (0,1) и (2,3).
Итог
m[i, j]— элемент,m[i]— строка,m[:, j]— столбец;m[r1:r2, c1:c2]— прямоугольник, правые границы не входят;- срез — окно в те же данные; копия —
.copy(); a[[i1, i2, ...]]— элементы по списку индексов, в заданном порядке.