Индексация и срезы в NumPy

Индексация и срезы в NumPy NumPy

Привет! Мы уже научились создавать массивы и получать информацию о них. Теперь пришло время научиться извлекать данные из массивов — это одна из самых частых операций в NumPy.

В этой статье мы разберём:

  • Индексацию одномерных массивов
  • Индексацию многомерных массивов
  • Срезы (slicing)
  • Булеву индексацию
  • Views и копии

Что нужно знать перед началом

Для этого урока тебе понадобится:

  • Установленный NumPy
  • Базовое понимание массивов

Совет: Индексация в NumPy работает так же, как в списках Python, но с дополнительными возможностями.

Основная часть

Индексация одномерных массивов

В одномерных массивах индексация работает как в списках:

import numpy as np

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

print(arr[0])    # 10
print(arr[2])    # 30
print(arr[-1])   # 50 (последний элемент)
print(arr[-2])   # 40

Совет: Индексация начинается с 0. Отрицательные индексы отсчитываются с конца.

Индексация двумерных массивов

В двумерных массивах индексы разделяются запятой: [строка, столбец].

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])

print(arr[0, 0])   # 1 (первая строка, первый столбец)
print(arr[1, 2])   # 6 (вторая строка, третий столбец)
print(arr[2, 1])   # 8 (третья строка, второй столбец)

# Доступ к целой строке
print(arr[1])      # [4 5 6]

# Доступ к целому столбцу
print(arr[:, 1])   # [2 5 8]

Совет: Двоеточие : означает «все элементы по этому измерению».

Срезы (slicing) одномерных массивов

Срезы в NumPy работают как в списках:

arr = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

print(arr[2:7])    # [2 3 4 5 6]
print(arr[:5])     # [0 1 2 3 4]
print(arr[5:])     # [5 6 7 8 9]
print(arr[::2])    # [0 2 4 6 8] (каждый второй)
print(arr[::-1])   # [9 8 7 6 5 4 3 2 1 0] (в обратном порядке)

Совет: Срезы создают view (представление), а не копию данных.

Срезы многомерных массивов

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12]])

# Первые две строки, все столбцы
print(arr[0:2, :])
# [[1 2 3 4]
#  [5 6 7 8]]

# Все строки, столбцы 1-2
print(arr[:, 1:3])
# [[ 2  3]
#  [ 6  7]
#  [10 11]]

# Первые две строки, столбцы 1-2
print(arr[0:2, 1:3])
# [[2 3]
#  [6 7]]

# Каждая вторая строка, каждый второй столбец
print(arr[::2, ::2])
# [[1 3]
#  [9 11]]

Совет: Синтаксис срезов: [start:stop:step] для каждого измерения.

Булева индексация

Булева индексация позволяет выбирать элементы, удовлетворяющие условию.

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# Элементы больше 5
mask = arr > 5
print(mask)          # [False False False False False  True  True  True  True  True]
print(arr[mask])     # [ 6  7  8  9 10]

# Элементы чётные
print(arr[arr % 2 == 0])   # [2 4 6 8 10]

# Элементы между 3 и 7
print(arr[(arr > 3) & (arr < 7)])   # [4 5 6]

Совет: Для сложных условий используй & (И) и | (ИЛИ).

Булева индексация в двумерных массивах

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])

# Элементы больше 4
print(arr[arr > 4])   # [5 6 7 8 9]

# Строки, где сумма > 10
rows = np.sum(arr, axis=1)
print(rows)          # [6 15 24]
print(arr[rows > 10]) # [[4 5 6]
                      #  [7 8 9]]

Views vs копии

Срезы в NumPy создают view (представление), а не копию данных.

arr = np.array([1, 2, 3, 4, 5])
sub = arr[1:4]
sub[0] = 99

print(arr)   # [1 99 3 4 5] (исходный массив изменился)
print(sub)   # [99 3 4]

Совет: Чтобы создать копию, используй .copy().

arr = np.array([1, 2, 3, 4, 5])
sub = arr[1:4].copy()
sub[0] = 99

print(arr)   # [1 2 3 4 5] (не изменился)
print(sub)   # [99 3 4]

Fancy indexing (индексация списком)

arr = np.array([10, 20, 30, 40, 50, 60])

# Индексация списком индексов
indices = [0, 2, 4]
print(arr[indices])   # [10 30 50]

# Индексация массивом индексов
indices = np.array([1, 3, 5])
print(arr[indices])   # [20 40 60]

# Двумерная индексация
arr2d = np.array([[1, 2], [3, 4], [5, 6]])
rows = [0, 2]
cols = [1, 0]
print(arr2d[rows, cols])   # [2 5]

Задачи для закрепления

Задача 1. Извлеки элементы с индексами 1, 3, 5 из массива [10, 20, 30, 40, 50, 60].

Задача 2. Извлеки второй столбец из матрицы 3×3.

Задача 3. Извлеки подмассив 2×2 из центра матрицы 4×4.

Задача 4. Выбери все чётные числа из массива.

Задача 5. Измени форму массива с помощью срезов.

Ответы:

Задача 1.

import numpy as np
arr = np.array([10, 20, 30, 40, 50, 60])
result = arr[[1, 3, 5]]
print(result)   # [20 40 60]

Задача 2.

arr = np.array([[1, 2, 3],
                [4, 5, 6],
                [7, 8, 9]])
col = arr[:, 1]
print(col)   # [2 5 8]

Задача 3.

arr = np.array([[1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12],
                [13, 14, 15, 16]])
center = arr[1:3, 1:3]
print(center)
# [[ 6  7]
#  [10 11]]

Задача 4.

arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
evens = arr[arr % 2 == 0]
print(evens)   # [2 4 6 8 10]

Задача 5.

arr = np.arange(12).reshape(3, 4)
print(arr)
sub = arr[0:2, 1:3]
print(sub)   # [[1 2]
             #  [5 6]]

Нюансы и подводные камни

  • Срезы создают view, а не копию. Изменение среза изменяет исходный массив.
  • Булева индексация всегда создаёт копию. Изменение результата не влияет на оригинал.
  • При использовании списка индексов (fancy indexing) создаётся копия.
  • arr[0:5] и arr[0:5].copy() — разное поведение.
  • В многомерных массивах arr[1] и arr[1, :] дают одинаковый результат, но синтаксис может ввести в заблуждение.
  • arr[:, 1] — это копия столбца, а не view. В отличие от строк.

Частые ошибки и как их избежать

Ошибка 1: Изменение среза меняет оригинал

Неправильно:

arr = np.array([1, 2, 3, 4, 5])
sub = arr[1:4]
sub[0] = 99
print(arr)   # [1 99 3 4 5] — неожиданно!

Правильно:

sub = arr[1:4].copy()
sub[0] = 99
print(arr)   # [1 2 3 4 5]

Ошибка 2: Индекс вне границ

Проверяй shape перед индексацией.

Ошибка 3: Путаница между arr[0, 1] и arr[0][1]

Для многомерных массивов используй arr[0, 1] — это быстрее и чище.

Шпаргалка

Что нужноКак пишется
Элемент (i, j)arr[i, j]
Строка iarr[i, :]
Столбец jarr[:, j]
Срез строкarr[1:5, :]
Срез столбцовarr[:, 2:6]
Булева индексацияarr[arr > 5]
Копия срезаarr[1:4].copy()
Fancy indexingarr[[0, 2, 4]]

Заключение

Сегодня мы:

  • Научились индексировать одномерные и многомерные массивы
  • Использовали срезы для извлечения подмассивов
  • Применяли булеву индексацию
  • Поняли разницу между views и копиями

КВИЗ

Что дальше?

Оцените статью
IMI-DS - PYTHON LERNEN
Содержание
Оглавление ×