Как вы решаете проблему пропущенных данных?

Обработка пропущенных данных — это важнейший этап подготовки данных для анализа, визуализации и машинного обучения. Пропущенные значения (NaN, NULL, NA, пустые ячейки) могут привести к искажённым результатам статистики, снижению точности моделей и сбоям в вычислениях. Выбор подхода зависит от природы данных, доли пропусков, типа переменной, механизма их появления и целей анализа.

Причины появления пропущенных данных

  1. Ошибки ввода или сбора данных — человеческий фактор, сбой сенсора, обрыв соединения.

  2. Неприменимость вопроса — в анкетах: "Сколько детей?" — пропуск у бездетных.

  3. Неполная интеграция источников — при объединении баз данных.

  4. Фильтрация пользователей — не все проходят через все этапы воронки.

  5. Конфиденциальность — отказ пользователя делиться данными (доход, возраст).

Типы механизмов пропусков (по Rubin)

  1. MCAR (Missing Completely At Random)
    Пропуски не зависят ни от наблюдаемых, ни от ненаблюдаемых переменных. Пример: случайная потеря данных из-за сбоя.

  2. MAR (Missing At Random)
    Пропуски зависят от наблюдаемых переменных. Например, доход может отсутствовать чаще у студентов.

  3. MNAR (Missing Not At Random)
    Пропуски зависят от самого пропущенного значения. Например, люди с высоким доходом чаще скрывают его.

Выбор метода зависит от типа пропусков. MCAR — самый безопасный случай для удаления или простого заполнения.

Шаги в обработке пропущенных значений

1. Обнаружение пропусков

Инструменты:

Python (pandas):

```python
df.isnull().sum()
df.isnull().mean()
df.info()

**SQL:  
<br/>**SELECT COUNT(\*) FROM table WHERE column IS NULL;

- **BI-системы:** фильтры и сводные таблицы  


Анализируют:

- долю пропусков в столбцах  

- распределение по строкам и группам  

- кросс-связи с другими переменными  


#### **2\. Удаление пропущенных данных**

**Удаление строк (наблюдений)**

df.dropna()

Применяется, если:

- доля пропусков мала (например, < 5%)  

- пропуски случайны (MCAR)  

- удаление не влияет на распределение  


**Удаление столбцов (признаков)**

df.drop(columns=\['feature_with_many_nans'\])

Подходит, если:

- столбец заполнен <1030%  

- переменная нерелевантна или имеет низкую значимость  


Недостаток: может привести к потере информации или смещению выборки.

#### **3\. Заполнение (импутация) пропусков**

##### **Простая импутация**

- **Среднее (mean):  
    **df\['col'\].fillna(df\['col'\].mean())  
    Используется для количественных данных с нормальным распределением.  

- **Медиана (median):  
    **Подходит при наличии выбросов или смещённого распределения.  

- **Мода (mode):  
    **Применяется к категориальным и порядковым переменным.  

- **Константа (например, 0 или "Unknown"):  
    **Явное указание, что значение было пропущено.  


##### **Групповая импутация**

Заполнение по группам, где есть логическая связь:

```python  
df\['income'\] = df.groupby('education_level')\['income'\].transform(lambda x: x.fillna(x.median()))

Применяется, если пропуски зависят от других признаков.

Заполнение по предыдущему/следующему значению
  • Forward fill (ffill):
    Полезно для временных рядов.
    df.fillna(method='ffill')

  • Backward fill (bfill):
    Использует следующее ненулевое значение.
    df.fillna(method='bfill')

4. Импутация на основе моделей

Использует другие признаки для предсказания пропущенных значений.

Регрессия (для количественных переменных)

Обучается модель (линейная, случайный лес и др.) на непустых значениях:

from sklearn.ensemble import RandomForestRegressor
\# Обучение модели на непустых
known = df\[df\['target'\].notnull()\]
unknown = df\[df\['target'\].isnull()\]
model = RandomForestRegressor()
model.fit(known\[features\], known\['target'\])
\# Предсказание пропусков
df.loc\[df\['target'\].isnull(), 'target'\] = model.predict(unknown\[features\])
Классификация (для категориальных переменных)

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

5. KNN-импутация (K-Nearest Neighbors)

Заполнение значений по ближайшим (похожим) наблюдениям:

from sklearn.impute import KNNImputer
imputer = KNNImputer(n_neighbors=5)
df_filled = imputer.fit_transform(df)
  • Учитывает "соседей" по всем признакам

  • Подходит для смешанных типов данных

  • Дорогой по вычислениям при больших выборках

6. Множественная импутация (Multiple Imputation)

Создаются несколько реализаций пропущенных значений с учётом неопределённости, затем объединяются оценки.

Пример: алгоритм MICE (Multiple Imputation by Chained Equations)

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
imp = IterativeImputer()
df_imputed = imp.fit_transform(df)
  • Повторяет взаимосвязи между признаками

  • Полезен для анализа с оценкой доверия

  • Сложный, используется в научных/медицинских задачах

7. Внесение признака "было пропущено"

Полезная техника: добавить бинарный индикатор наличия пропуска:

df\['col_nan_flag'\] = df\['col'\].isnull().astype(int)
  • Может быть полезна для моделей (например, если само наличие пропуска связано с поведением клиента)

  • Позволяет модели "узнать", что признак отсутствовал

Визуализация пропусков

Heatmap (Seaborn/Matplotlib):

```python
import seaborn as sns
sns.heatmap(df.isnull(), cbar=False)

**Missingno:  
**Пакет для Python, визуализирует пропуски графически:  
<br/>```python  
import missingno as msno
msno.matrix(df)
msno.heatmap(df)  

Позволяет определить зависимости пропусков между признаками, их локализацию, долю и структуру.

Выбор стратегии в зависимости от контекста

Ситуация Рекомендуемый подход
<5% пропусков, MCAR Удаление строк
--- ---
Категориальные переменные Заполнение модой, "Unknown", классификация
--- ---
Количественные переменные (нормальное распределение) Среднее, KNN, регрессия
--- ---
Есть сильная связь с другими переменными Групповая или модельная импутация
--- ---
MNAR или чувствительная информация Множественная импутация, моделирование пропусков
--- ---
Временные ряды ffill / bfill
--- ---
Big Data / ML Импутация + индикаторы пропуска
--- ---

Потенциальные риски при неправильной обработке

  • Смещение распределения: замена средним "сглаживает" данные.

  • Утрата корреляций: неправильная импутация искажает взаимосвязи.

  • Увеличение шума: особенно при заполнении случайными или неинформативными значениями.

  • Ложные зависимости: например, label-encoding с порядком для номинальных пропусков.

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