Пропущенные значения в Data Science: как работать с missing values

Как работать с missing values без хаоса: что на самом деле означают пропуски, когда их удалять, а когда превращать в полезный сигнал для модели.

Содержание Следующие статьи
Содержание Пропущенные значения в Data Science: как работать с missing values
  1. Почему пропуск — это не всегда просто отсутствие числа
  2. Почему нельзя всегда просто заменить средним
  3. Как мыслить про пропуски по-взрослому
  4. Как это делается в Python

Почему пропуск — это не всегда просто отсутствие числа

Когда в таблице появляется `NaN`, первая реакция обычно техническая: надо как-то заполнить или удалить. Но пропуск — это еще и сообщение о процессе сбора данных. Иногда данных нет случайно. Иногда значение отсутствует, потому что пользователь не дошел до этапа формы. Иногда поле не применимо к части объектов. Иногда система сломалась. И от этого происхождения зависит, что с пропуском делать дальше.

Поэтому работа с missing values — это не только preprocessing, но и диагностика самого процесса появления данных.

Почему нельзя всегда просто заменить средним

Формула: раздел математики — математическая статистика
$$ x_{filled} = \begin{cases} x, & x \neq \varnothing \\ \bar{x}, & x = \varnothing \end{cases} $$
Что означает эта формула

Заполнение средним — один из самых простых способов иммутации. Он удобен, но может скрывать структуру пропусков и искусственно сглаживать распределение признака.

Что означает каждый символ
  • x_{filled} — значение признака после заполнения
  • x — исходное наблюдение, если оно известно
  • \varnothing — отсутствующее значение
  • \bar{x} — среднее по наблюдаемым значениям признака

В некоторых задачах такое заполнение нормально работает как baseline. Но если пропуски несут содержательную информацию, среднее может стереть важный сигнал. Например, сам факт отсутствия дохода в анкете может быть информативнее, чем приблизительно подставленная цифра.

Как мыслить про пропуски по-взрослому

Сначала полезно понять масштаб проблемы: где пропусков много, а где мало. Потом — проверить, не связаны ли они с target или сегментами данных. После этого уже выбирать стратегию: удалить строки, удалить признак, заполнить медианой, модой, модельной иммутацией или добавить бинарный индикатор пропуска. Очень часто сильным решением оказывается комбинация: аккуратное заполнение плюс отдельный флаг, показывающий, что значение было отсутствующим.

То есть цель не «убрать NaN любой ценой», а сохранить максимальное количество честной информации о данных.

Как это делается в Python

example.pyPython
import pandas as pd  # создаем пример таблицы с пропусками в числовом признаке
from sklearn.impute import SimpleImputer  # используем базовую иммутацию для числового столбца

frame = pd.DataFrame({  # задаем признак с missing values
    'income': [45000, None, 72000, None, 61000],  # часть значений неизвестна
})
frame['income_missing'] = frame['income'].isna().astype(int)  # сохраняем отдельный индикатор пропуска как возможный сигнал
imputer = SimpleImputer(strategy='median')  # выбираем медиану как более устойчивое заполнение
frame['income_filled'] = imputer.fit_transform(frame[['income']])  # подставляем медиану вместо отсутствующих значений
print(frame)  # сравниваем исходный столбец, индикатор пропуска и заполненную версию

Хороший preprocessing пропусков начинается именно здесь: мы не просто маскируем дыру, а стараемся сохранить смысл того, что в данных чего-то не было.

Что читать дальше

Связанные статьи по этой теме

Canary deployment для моделей: как выкатывать новую версию без лишнего риска Latency в ML API: почему быстрая модель важна не меньше точной Batch inference и real-time inference: как выбирать режим работы модели
Вернуться в блог