NaN в числовых массивах: обнаружение и nan-устойчивые агрегаты
Содержание курса
Обнаружение NaN: np.isnan, np.any и np.all
Раз сравнение через == не работает, NumPy предоставляет специальную функцию — np.isnan. Она обходит каждый элемент массива и возвращает True ровно там, где стоит NaN:
import numpy as np
arr = np.array([1.0, np.nan, 3.0, np.nan, 5.0])
mask = np.isnan(arr)
print(mask) # [False True False True False]
print(mask.shape) # (5,)
print(mask.dtype) # bool
Результат — булев массив той же формы, что входной. Его можно сразу использовать для индексации: arr[~mask] даст только элементы без NaN.
Есть ли в массиве хотя бы один NaN?
Просматривать булев массив глазами неудобно. Для быстрой проверки используют np.any и np.all.
np.any(mask) возвращает True, если в mask есть хотя бы один True — то есть хотя бы один NaN в исходном массиве:
print(np.any(np.isnan(arr))) # True
np.all(mask) возвращает True только если все элементы mask равны True — то есть весь массив состоит из NaN:
print(np.all(np.isnan(arr))) # False — есть и обычные числа
all_nan = np.array([np.nan, np.nan, np.nan])
print(np.all(np.isnan(all_nan))) # True
Оба вызова принимают булев массив и возвращают скалярный bool — удобно для ветвления в коде:
if np.any(np.isnan(arr)):
print("Массив содержит пропуски")
Комбинация np.isnan + np.any — стандартный способ проверить массив перед агрегацией. Если np.any(np.isnan(arr)) вернул True, нельзя просто взять np.sum или np.mean и получить осмысленный результат — почему именно, разберём в следующем разделе.
