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

Теперь, когда мы научились загружать данные из разных источников — будь то CSV, Excel или SQL — настало время сделать следующий шаг. Данные редко приходят в идеальном виде. Часто они содержат пропуски, дублируются или включают ошибки. Если не обработать эти проблемы, любой анализ, даже самый изящный, может привести к ложным выводам.

Представьте, что вы строите дом. Фундамент — это качество данных. Неважно, насколько красивы стены и крыша, если фундамент треснут — всё рухнет. Так и в аналитике: грязные данные = ложные решения.

В этой теме мы сосредоточимся на трёх ключевых типах проблем:

  • Пропущенные значения (NaN)
  • Дубликаты
  • Некорректные данные (неверные типы, выбросы, форматы)

Мы разберём, как их обнаруживать и как принимать взвешенные решения по их обработке.

Диагностика: как понять, что данные "грязные"?

Прежде чем чистить, нужно понять, что именно требует чистки. Начнём с простого: загрузим датасет с данными о продажах.

import pandas as pd

# Загружаем данные (как вы уже умеете из темы "Чтение и запись данных")
df = pd.read_csv('sales_data_dirty.csv')
df.head()

Теперь посмотрим общую информацию:

df.info()

Этот метод покажет:

  • Количество непустых значений в каждом столбце
  • Типы данных
  • Общее число строк

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

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

df.isna().sum()

Это покажет количество NaN в каждом столбце.

💡 Совет: Для визуализации пропусков можно использовать библиотеку missingno. Она строит тепловую карту, где пропуски видны как белые полосы. Это особенно полезно при работе с большими таблицами.

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

Пропущенные значения — одна из самых частых проблем. В Pandas они обозначаются как NaN (Not a Number).

Удалять или заполнять? Это зависит от:

  • Объёма пропусков
  • Типа данных
  • Контекста

Вариант 1: Удаление строк или столбцов

Если пропусков меньше 5% и они распределены случайно — можно удалить строки:

df_clean = df.dropna(subset=['price'])  # удаляем строки, где цена — NaN

Если в столбце больше 60% пропусков, и он не критичен — возможно, стоит удалить весь столбец:

df_clean = df.drop(columns=['promo_code'])  # если коды акций почти везде пустые

⚠️ Осторожно: если вы удалите 40% строк, ваш анализ может потерять репрезентативность. Это как опросить только 60 человек из 100 — выборка перестаёт быть объективной.

Вариант 2: Заполнение значений

Более аккуратный подход — заполнить пропуски.

Для числовых данных:

  • Среднее (mean()) — если распределение близко к нормальному
  • Медиана (median()) — если есть выбросы
  • Интерполяция — если данные временные
df['price'].fillna(df['price'].median(), inplace=True)

Для категориальных данных (например, region, category):

  • Мода (mode()) — самое частое значение
  • Или специальное значение: "Unknown"
df['region'].fillna('Unknown', inplace=True)

📌 Правило: никогда не заполняйте категориальную переменную средним. Это бессмысленно и сломает анализ.

Удаление дубликатов

Дубликаты — это одинаковые строки, которые попали в данные дважды. Часто из-за ошибок выгрузки или дублирования действий.

Проверим:

df.duplicated().sum()  # сколько полных дубликатов?

Удалим:

df_clean = df.drop_duplicates()

Но бывает частичное дублирование. Например, заказ с одинаковым order_id, но разный регистр в имени: "Иванов" и "иванов".

Для таких случаев — сначала нормализуем данные:

df['customer_name'] = df['customer_name'].str.strip().str.lower()
df_clean = df.drop_duplicates(subset=['order_id'])

Теперь дубликаты по order_id будут найдены корректно.

Исправление некорректных значений

Иногда данные "не горят", но явно ошибочны.

Проблема 1: Неверные типы данных

Дата хранится как строка? Нужно исправить:

df['order_date'] = pd.to_datetime(df['order_date'], errors='coerce')

errors='coerce' превратит некорректные даты (например, "2023-02-30") в NaN, чтобы их можно было обработать отдельно.

Проблема 2: Выбросы

Цена товара — 999 999 рублей? При средней в 5 000? Это выброс.

Его можно:

  • Удалить
  • Заменить на верхний предел (например, 99-й перцентиль)
  • Исследовать: а вдруг это действительно редкий товар?

Для числовых столбцов полезно посмотреть статистику:

df['price'].describe()

Если max в 100 раз больше 75% — стоит проверить.

Проблема 3: Несоответствие форматов

Например, в столбце status значения: "Доставлен", "доставлен ", "в пути", "В Пути".

Нормализуем:

df['status'] = df['status'].str.strip().str.lower()

Теперь можно группировать и анализировать без ошибок.

Проверка результата и логирование

После очистки — обязательно проверьте:

print(f"Оригинальное количество строк: {len(df)}")
print(f"После очистки: {len(df_clean)}")
print(f"Пропуски осталось: {df_clean.isna().sum().sum()}")

Запишите, что вы сделали. Это важно для воспроизводимости:

🔹 Удалено 12 дубликатов
🔹 Пропуски в price заполнены медианой (499 руб.)
🔹 Пропуски в region заменены на "Unknown"
🔹 Некорректные даты приведены к формату datetime, ошибки — в NaN

Такой лог поможет вам или коллеге понять, почему были приняты те или иные решения.

Почему это важно для карьеры?

На практике 80% времени аналитика уходит на подготовку данных. Работодатели это знают.

Умение работать с "грязными" данными — ключевой навык, который отличает Junior от Middle.

В российских компаниях особенно часто встречаются данные из устаревших систем, где:

  • Даты в формате DD.MM.YY
  • Пробелы в начале строк
  • Дублирующиеся ID

Ваша способность быстро и аккуратно их обработать — прямой путь к доверию со стороны команды.

💼 Из практики: однажды я обнаружил, что в отчёте о прибыли 15% заказов были учтены дважды из-за дубликатов. После очистки — прибыль "снизилась", но зато цифра стала правдивой. Это спасло компанию от ошибочных инвестиций.

Что дальше?

Теперь, когда данные очищены, они готовы к анализу.

В следующей теме — Фильтрация, сортировка и выборка данных — мы научимся извлекать нужную информацию: например, "покажи топ-10 самых дорогих товаров за март".

Без очистки такие запросы могут выдать искажённые результаты. А теперь — у нас чистая основа.

Готовы превращать данные в инсайты? Поехали.