Логическая индексация

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

Логическая индексация — обращение к массиву по логической маске того же размера: остаются элементы, против которых стоит true.

Маска как фильтр

Сравнение применяется ко всей матрице сразу и возвращает логическую матрицу того же размера из нулей и единиц. Если подставить эту маску в индекс, MATLAB вернёт только отмеченные элементы — в виде вектора-столбца.

v = [3 8 1 9 4 7];
mask = v > 5        % 0 1 0 1 0 1 (логическая)
big = v(mask)        % 8 9 7 — элементы больше 5

Вывод:

mask =
  1x6 logical array
   0   1   0   1   0   1

big =
     8     9     7

Условие прямо в индексе

Маску не обязательно сохранять в переменную — условие можно записать прямо в скобках. Это идиоматичный MATLAB: v(v > 5) читается как «элементы v, которые больше 5». Несколько условий комбинируют поэлементными операторами & (И) и | (ИЛИ).

v = [3 8 1 9 4 7];
mid = v(v >= 4 & v <= 8)   % 8 4 7
v(v < 5) = 0               % обнулить всё, что меньше 5

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

find: где именно стоят единицы

Иногда нужны не сами значения, а их позиции. Функция find возвращает индексы ненулевых (истинных) элементов.

v = [3 8 1 9 4 7];
idx = find(v > 5)     % 2 4 6 — позиции больших элементов

Параллель с NumPy

Тем, кто знает NumPy, логическая индексация знакома: v[v > 5] делает ровно то же самое (булева маска). MATLAB-овский find соответствует numpy.nonzero / numpy.where. Сама идея — заменять циклы фильтрацией по маске — общая для обоих, и это центральный приём векторного мышления.

Как работает под капотом

Логическая маска — это специальный тип logical, занимающий 1 байт на элемент. MATLAB различает индексацию логическим массивом (берёт элементы, где true) и числовым (берёт по номерам). Поэтому v([1 0 1]) и v(logical([1 0 1])) дадут разное: первое — это номера 1, 0, 1 (а 0 недопустим как индекс → ошибка), второе — маска. Если хотите фильтровать, маска обязана быть типа logical, а не просто содержать нули и единицы.

Частые ошибки

  • Использовать &&/|| для поэлементных условий: они только для скаляров. Для массивов нужны & и |.
  • Передать в индекс числовой вектор из нулей и единиц вместо логического — получится индексация по номерам.
  • Ждать, что результат сохранит форму матрицы — фильтрация по маске возвращает вектор-столбец.

Подсчёт и проверки по маске

Логические маски полезны не только для выборки, но и для статистики по условию. Поскольку логический true в арифметике равен единице, sum(v > 5) подсчитывает, сколько элементов превышают порог, а mean(v > 5) даёт их долю. Функции any и all отвечают на вопросы «есть ли хоть один?» и «все ли?» — например, any(isnan(v)) проверяет, нет ли в данных пропусков. Эти конструкции заменяют целые циклы с подсчётом и читаются почти как фраза на русском.

Замена значений и очистка данных

На практике логическая индексация чаще всего применяется именно для очистки реальных данных. Измерения приходят с выбросами, пропусками, отрицательными значениями там, где их быть не должно. Одна строка v(v > threshold) = threshold обрезает выбросы сверху (клиппинг); v(isnan(v)) = 0 заполняет пропуски; комбинация условий через & и | выделяет нужное окно значений. Без масок каждая такая операция превратилась бы в цикл с if — медленный и громоздкий. С масками подготовка данных к расчёту умещается в несколько выразительных строк, и это одна из причин, почему MATLAB так удобен для разведочного анализа.

Итоги

  • Сравнение даёт логическую маску; v(маска) отбирает элементы.
  • Присваивание по условию (v(v<0)=0) чистит данные без циклов.
  • find возвращает позиции; для массивов комбинируйте условия & и |.
Проверьте себя
1. Что вернёт v(v > 5) для v = [3 8 1 9]?
A[0 1 0 1]
B[8 9]
C[2 4]
DОшибку
2. Какой оператор используют для поэлементного И между массивами?
A&&
B&
Cand
D+
3. Что возвращает find(v > 5)?
AСами элементы больше 5
BПозиции (индексы) элементов больше 5
CИх количество
DЛогическую маску