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

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

Привет! Мы уже умеем индексировать массивы по позициям и срезам. Но что, если нужно выбрать элементы по сложным условиям? Или выбрать произвольные элементы по списку индексов? Здесь на помощь приходят булева индексация и fancy indexing.

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

  • Булеву индексацию: выборка по условиям
  • Комбинирование условий
  • Fancy indexing: индексация списками
  • Индексация с помощью массивов
  • Практические примеры

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

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

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

Совет: Булева индексация — это самый удобный способ фильтрации данных в NumPy.

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

Что такое булева индексация

Булева индексация — это выбор элементов массива с помощью массива булевых значений (True/False).

import numpy as np

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

# Создаём булев массив
mask = arr > 5
print(mask)   # [False False False False False  True  True  True  True  True]

# Применяем индексацию
result = arr[mask]
print(result)   # [ 6  7  8  9 10]

Совет: Булев массив должен быть той же длины, что и индексируемый массив.

Однострочная фильтрация

# Все элементы больше 5
print(arr[arr > 5])   # [ 6  7  8  9 10]

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

# Все элементы от 3 до 7 (включительно)
print(arr[(arr >= 3) & (arr <= 7)])   # [3 4 5 6 7]

Совет: Используй & (И) и | (ИЛИ) для комбинирования условий.

Комбинирование условий

# Элементы больше 3 и чётные
print(arr[(arr > 3) & (arr % 2 == 0)])   # [4 6 8 10]

# Элементы меньше 3 или больше 8
print(arr[(arr < 3) | (arr > 8)])   # [1 2 9 10]

# Сложное условие с отрицанием
print(arr[~((arr > 3) & (arr < 8))])   # [1 2 3 8 9 10]

Важно: В NumPy нельзя использовать and/or для комбинирования условий. Используй & и |.

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

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

# Все элементы больше 5
print(arr_2d[arr_2d > 5])   # [6 7 8 9]

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

# Столбцы, где первый элемент > 2
print(arr_2d[:, arr_2d[0] > 2])   # [[3]
                                  #  [6]
                                  #  [9]]

Изменение элементов по условию

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

# Заменяем все элементы > 3 на 0
arr[arr > 3] = 0
print(arr)   # [1 2 3 0 0]

# Увеличиваем все чётные на 1
arr = np.array([1, 2, 3, 4, 5])
arr[arr % 2 == 0] += 1
print(arr)   # [1 3 3 5 5]

Совет: Булева индексация работает не только для чтения, но и для записи.

Что такое fancy indexing

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]

# Отрицательные индексы
indices = [-1, -3, -5]
print(arr[indices])   # [60 40 20]

Fancy indexing в многомерных массивах

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

# Выбор строк
rows = [0, 2]
print(arr_2d[rows])   # [[1 2 3]
                      #  [7 8 9]]

# Выбор столбцов
cols = [1, 0]
print(arr_2d[:, cols])   # [[2 1]
                         #  [5 4]
                         #  [8 7]]

# Выбор элементов по координатам
rows = [0, 1, 2]
cols = [2, 1, 0]
print(arr_2d[rows, cols])   # [3 5 7]

Совет: При fancy indexing с несколькими массивами они работают как координаты: arr[rows, cols] выбирает элементы (0,2)(1,1)(2,0).

Комбинирование булевой индексации и fancy indexing

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

# Сначала фильтруем, потом выбираем по индексам
mask = arr > 25
filtered = arr[mask]   # [30 40 50 60]
indices = [0, 2]
result = filtered[indices]   # [30 50]

# Или в одну строку
result = arr[arr > 25][[0, 2]]
print(result)   # [30 50]

Полный пример

import numpy as np

# Создаём массив
arr = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

# Булева индексация
print("Элементы > 5:", arr[arr > 5])
print("Чётные:", arr[arr % 2 == 0])
print("Чётные и > 4:", arr[(arr % 2 == 0) & (arr > 4)])

# Изменение по условию
arr_copy = arr.copy()
arr_copy[arr_copy > 5] = 0
print("После замены > 5:", arr_copy)

# Fancy indexing
print("Индексы [0, 3, 7]:", arr[[0, 3, 7]])
print("Индексы [-1, -3, -5]:", arr[[-1, -3, -5]])

# Многомерный пример
arr_2d = np.arange(1, 17).reshape(4, 4)
print("Исходная матрица:\n", arr_2d)

# Булева индексация
print("Элементы > 10:", arr_2d[arr_2d > 10])

# Fancy indexing
rows = [0, 2]
cols = [1, 3]
print("Элементы (0,1), (2,3):", arr_2d[rows, cols])

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

Задача 1. Выбери все элементы массива, которые больше 5.

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

Задача 3. Замени все элементы больше 10 на 0.

Задача 4. Выбери элементы с индексами [1, 3, 5] из массива.

Задача 5. Выбери элементы (0,0), (1,1), (2,2) из матрицы 3×3.

Ответы:

Задача 1.

arr[arr > 5]

Задача 2.

arr[arr % 2 == 0]

Задача 3.

arr[arr > 10] = 0

Задача 4.

arr[[1, 3, 5]]

Задача 5.

arr_2d[[0, 1, 2], [0, 1, 2]]

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

Булева индексация создаёт копию

При булевой индексации создаётся копия данных. Изменения в результате не влияют на исходный массив.

Fancy indexing создаёт копию

При fancy indexing также создаётся копия, а не view.

& и | вместо and/or

В NumPy для булевых массивов используй & и |, а не and/or.

Сложные условия

Для сложных условий используй скобки для группировки.

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

Ошибка 1: Использование and/or вместо &/|

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

arr[(arr > 3) and (arr < 8)]

Правильно:

arr[(arr > 3) & (arr < 8)]

Ошибка 2: Разная длина булевого массива

Булев массив должен быть той же длины, что и индексируемый массив.

Ошибка 3: Изменение результата булевой индексации

Изменяй исходный массив напрямую, а не результат.

Шпаргалка

Что нужноКак пишется
Условие > 5arr[arr > 5]
Комбинация условийarr[(arr > 3) & (arr < 8)]
Чётныеarr[arr % 2 == 0]
Замена по условиюarr[arr > 5] = 0
Индексы спискомarr[[0, 2, 4]]
Координатыarr[[0, 1], [2, 3]]

Заключение

Сегодня мы:

  • Узнали, что такое булева индексация
  • Научились фильтровать данные по условиям
  • Познакомились с fancy indexing
  • Применили на практике

КВИЗ

Что дальше?

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