Меня зовут Руслан Каллагов, я системный аналитик в Лаборатории Globus — партнёре Нетологии по стажировкам на курсах ИТ-профессий. Уже 4,5 года я работаю в проектировании программного обеспечения и верю в инженерный подход к подготовке данных. Специально для хабровчан собрал практическое руководство по подготовке, очистке и предобработке данных для анализа и машинного обучения. В нём объясняю ключевые этапы подготовки данных, показываю примеры кода, даю чек-листы и алгоритмы действий.
Я считаю, что подготовка данных — самый недооценённый этап аналитики. Его не видно в демо, за него редко благодарят, и почти никогда не закладывают время. Но именно здесь решается главный вопрос проекта: можно ли этим данным доверять вообще.
Данные почти всегда «грязные». Подготовка = pipeline, а не набор действий. Очистка ≠ предобработка. Масштабирование критично для моделей. Если процесс не автоматизирован — это долг.TL;DR для тех, кто не хочет долго читать
По данным ежегодных опросов Anaconda (2023, 2024), подготовка и очистка данных остаются наиболее времязатратными задачами дата-специалистов — вне зависимости от того, насколько автоматизирован их рабочий процесс. Исторически оценки варьировались от 45 до 80% рабочего времени (Anaconda 2020, CrowdFlower 2016), и хотя инструменты за последние годы стали лучше, задача никуда не исчезла.
Какие термины используются в статье:
-
очистка данных (data cleansing) — исправление ошибок (дубликатов, пропусков, выбросов, некорректных значений);
-
предобработка данных (data preprocessing, wrangling) — преобразование (типы, масштабирование, кодирование, признаки);
-
подготовка данных (data preparation) — общий процесс (включает исследование → очистку → преобразование → проверку).
Очистка отвечает на вопрос: «Что в данных сломано».
Предобработка: «Как привести данные в рабочий вид».
Подготовка: «Как пройти путь от сырого набора до данных, которым можно доверять».
В этой статье мы используем термин «подготовка данных» как общий, и внутри него разберём очистку и предобработку как отдельные этапы.
Почему данные почти всегда «грязные»
В реальных проектах данные редко бывают аккуратными. Они содержат пропуски, дубликаты, ошибки формата и противоречия — такие данные принято называть «грязными» (dirty data). Это не исключение, а правило: данные поступают из разных систем, вводятся вручную, мигрируют между платформами.
Пример «грязных» данных:
| user_id | age | salary | signup_date | department |
| ------- | --- | ------ | ----------- | ---------- |
| 101 | 25 | 50000 | 2023-01-10 | Sales |
| 102 | NaN | 60000 | 10.01.2023 | Marketing |
| 103 | -5 | 70000 | 2023/01/12 | IT |
| 101 | 25 | 50000 | 2023-01-10 | Sales |
| 104 | 200 | NULL | 2023-01-15 | HR |
Типичные проблемы «грязных» данных: пропуски (NaN, NULL), дубликаты, выбросы, разные форматы, логические ошибки. Ещё пример:
import pandas as pd
df = pd.read_csv("data.csv")
df.info()
df.isna().sum()
df.duplicated().sum()
df.describe()
Проблема особенно актуальна для российского рынка: уровень цифровой зрелости российских организаций на конец 2025 года составлял лишь 45%, а значит, большинство компаний ещё не выстроили системное управление качеством данных. Даже в зрелых организациях проекты ИИ и аналитическая отчётность нередко опираются на грязные и разрозненные данные, что снижает доверие и к моделям, и к аналитике.
Этапы подготовки данных: от хаоса к системе
Чтобы не работать на ощупь, подготовку данных нужно выстраивать как пайплайн: исследование → очистка → объединение → предобработка → валидация.
1. Исследование и профилирование данных
На этом этапе мы ничего не исправляем — мы понимаем данные.
Что делаем
-
Смотрим структуру.
-
Проверяем типы.
-
Считаем пропуски.
-
Анализируем распределения.
-
Ищем аномалии.
Пример:
df.info()
df.isna().sum()
df.describe(include="all")
Критерии успеха
Вы можете ответить:
-
какие поля проблемные;
-
где риски;
-
какие шаги очистки нужны.
2. Очистка данных
Теперь убираем ошибки.
Что делаем
Дубликаты:
df = df.drop_duplicates()
Пропуски:
df["salary"] = df["salary"].fillna(df["salary"].median())
Ошибки и выбросы:
df = df[df["age"].between(0, 120)]
Критерии успеха
Что имеем в итоге:
-
данные логически корректны;
-
нет критичных аномалий;
-
структура не разрушена.
3. Объединение данных
Если источников несколько, их нужно согласовать.
df = users.merge(orders, on="user_id", how="left")
Риски
-
Потеря строк.
-
Дубликаты после join.
-
Несовпадение ключей.
Критерии успеха
-
Данные согласованы.
-
Ключи валидны.
-
Нет размножения строк.
4. Предобработка и преобразование данных
Теперь приводим данные в рабочий вид.
Что делаем
-
Преобразуем типы.
-
Кодируем категории.
-
Создаём признаки.
-
Масштабируем числовые данные.
Важный этап: масштабирование признаков
Масштабирование нужно, чтобы признаки были сопоставимы.
Если один признак — в тысячах, а другой — в единицах, модель будет считать первый важнее.
Основные методы
StandardScaler: центрирует данные, стандартное отклонение = 1.
MinMaxScaler: приводит к диапазону [0, 1].
RobustScaler: устойчив к выбросам.
Пример:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[["age", "salary"]] = scaler.fit_transform(df[["age", "salary"]])
Критерии успеха
-
Признаки сопоставимы.
-
Модель обучается стабильнее.
-
Нет перекоса из-за масштаба.
5. Проверка качества данных
Финальный контроль. Пример:
assert df["user_id"].notna().all()
assert df["age"].between(-5, 5).all()
Критерии успеха
-
Данные проходят проверки.
-
Пайплайн воспроизводим.
-
Можно использовать в проде.
Практический пример: полный цикл
import pandas as pd
from sklearn.preprocessing import StandardScaler
df = pd.read_csv("users.csv")
# 1. Очистка
df = df.drop_duplicates()
df["salary"] = df["salary"].fillna(df["salary"].median())
df = df[df["age"].between(0, 120)]
# 2. Преобразование
df["signup_date"] = pd.to_datetime(df["signup_date"], errors="coerce")
# 3. Масштабирование
scaler = StandardScaler()
df[["age", "salary"]] = scaler.fit_transform(df[["age", "salary"]])
# 4. Валидация
assert df["user_id"].notna().all()
6. Приведение типов и форматов
На этом этапе данные приводят в вид, с которым можно работать дальше:
-
строки → числа;
-
даты → datetime;
-
единицы измерения → к одному стандарту.
Если типы данных некорректны, дальше почти гарантированы баги от неправильных расчётов до падения пайплайнов.
7. Кодирование и масштабирование признаков
Для моделей данные почти всегда нужно преобразовать:
-
категориальные признаки → закодировать;
-
числовые → масштабировать.
Пример:
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[['age', 'salary']] = scaler.fit_transform(df[['age', 'salary']])
Это критично для алгоритмов, чувствительных к масштабу признаков.
8. Проверка качества после очистки
После всех преобразований нужно задать себе простой вопрос: «Стали ли данные лучше, чем были?»
Минимум, что стоит проверить:
-
не потеряли ли вы важные сегменты;
-
не изменились ли распределения радикально;
-
не появились ли новые аномалии.
Если вы не смотрите на данные после очистки, вы работаете вслепую.
Инструменты для подготовки данных: что использовать и как именно
На этом этапе обычно возникает вопрос: «Окей, понятно, что делать. А какие инструменты для этого использовать?».
Ниже — практический минимум, который закрывает большинство задач.
pandas — базовый инструмент для очистки и анализа структуры данных
Если данные табличные (CSV, Excel, выгрузки из БД), то в большинстве проектов работа начинается именно здесь.
Когда использовать:
-
первичная загрузка данных;
-
поиск дубликатов и пропусков;
-
базовая очистка и трансформации;
-
быстрый анализ структуры.
Как применять на практике:
import pandas as pd
df = pd.read_csv('data.csv')
# Общая информация о данных
df.info()
# Количество пропусков по столбцам
df.isna().sum()
# Удаление дубликатов
df = df.drop_duplicates()
# Приведение типов
df['created_at'] = pd.to_datetime(df['created_at'])
Практический совет: если вы не запускали info() и isna().sum(), вы ещё не начинали подготовку данных.
Pandera — валидация данных по правилам (как тесты, только для данных)
Pandera позволяет описывать ожидания от данных в виде схем: типы, диапазоны, обязательные поля. Это особенно полезно, когда данные приходят регулярно.
Когда использовать:
-
данные обновляются ежедневно или по расписанию;
-
важно ловить ошибки до анализа;
-
нужно формализовать требования к данным.
Как применять на практике:
import pandera as pa
from pandera import Column, DataFrameSchema
schema = DataFrameSchema({
"user_id": Column(int, nullable=False),
"age": Column(int, pa.Check.between(0, 120)),
"salary": Column(float, nullable=True),
})
schema.validate(df)
Если данные не соответствуют ожиданиям, вы получите явное сообщение об ошибке — а не анализ, который незаметно даёт неверный результат.
Great Expectations — контроль качества данных на уровне пайплайна
Инструмент для описания ожиданий к данным и автоматической проверки качества.
Когда использовать:
-
ETL/ELT-пайплайны;
-
аналитика в продакшене;
-
нужно логировать проблемы с данными.
Типичные проверки:
-
столбец не должен быть пустым;
-
значения в диапазоне;
-
уникальность ключей;
-
допустимые категории.
Идея использования: данные пришли → прогнали проверки → только после этого пошли в аналитику или модель.
scikit-learn — предобработка признаков для моделей
Для машинного обучения подготовка данных почти всегда включает кодирование и масштабирование.
Когда использовать:
-
обучение моделей;
-
чувствительные к масштабу алгоритмы;
-
пайплайны ML.
Как применять на практике:
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
preprocessor = ColumnTransformer(
transformers=[
('num', StandardScaler(), ['age', 'salary']),
('cat', OneHotEncoder(handle_unknown='ignore'), ['department'])
]
)
X_prepared = preprocessor.fit_transform(df)
Важно: если предобработка не включена в пайплайн модели, вы почти гарантированно получите баг при переобучении или инференсе (применении обученной модели).
SQL — очистка данных как можно раньше
Если данные хранятся в БД, часть очистки лучше делать сразу на уровне SQL.
Когда использовать:
-
большие объёмы данных;
-
агрегации;
-
фильтрация мусора на входе.
Как применять на практике:
SELECT DISTINCT
user_id,
created_at,
salary
FROM users
WHERE salary IS NOT NULL
AND salary >= 0;
Чем раньше вы отсекаете мусор, тем дешевле и надёжнее аналитика.
Jupyter и Google Colab — интерактивная проверка и отладка
Jupyter и Google Colab — инструменты не для продакшена, но хорошо подходят для исследования данных.
Когда использовать:
-
исследовательская аналитика;
-
проверка гипотез;
-
визуальный контроль очистки.
Практика «очистил → сразу посмотрел график» экономит часы отладки.
Краткий чек-лист выбора инструмента
-
Нужно быстро посмотреть данные → pandas + Jupyter.
-
Нужно формализовать правила → Pandera.
-
Нужно следить за качеством в продакшене → Great Expectations.
-
Готовите данные для модели → scikit-learn.
-
Большие объёмы → SQL как можно раньше.
Ручная vs. автоматизированная предобработка: как это выглядит в реальной работе
На практике подготовка данных почти всегда проходит в два этапа:
-
ручная предобработка (exploration mode);
-
автоматизированная предобработка (production mode).
Это не два разных подхода. Это две стадии одного процесса.
Ручная предобработка: этап исследования
На старте вы почти всегда работаете вручную — в Jupyter Notebook или аналоге. Цель этапа — не почистить всё идеально, а:
-
понять структуру данных;
-
найти типичные ошибки;
-
протестировать гипотезы очистки;
-
выбрать стратегии обработки.
Пример — тот же «грязный» датасет пользователей:
import pandas as pd
df = pd.read_csv("users.csv")
# Смотрим структуру
df.info()
# Проверяем пропуски
df.isna().sum()
# Ищем дубликаты
df.duplicated().sum()
# Смотрим аномалии
df[df["age"] < 0]
df[df["age"] > 120]
Дальше — пробуем разные стратегии:
# Вариант 1: удалить дубликаты
df = df.drop_duplicates()
# Вариант 2: заполнить пропуски
df["salary"] = df["salary"].fillna(df["salary"].median())
# Вариант 3: убрать выбросы
df = df[df["age"].between(0, 120)]
На этом этапе допустимы эксперименты, временные решения, ручные правки.
Ключевая цель: понять, какие правила очистки вообще нужны.
Практический пример: пошаговая предобработка одного датасета
Соберём всё в единый процесс:
import pandas as pd
from sklearn.preprocessing import StandardScaler
df = pd.read_csv("users.csv")
Шаг 1. Первичный анализ
df.info()
df.isna().sum()
df.duplicated().sum()
Что выясняем:
-
есть пропуски в
salary; -
есть дубликаты;
-
есть некорректные значения возраста.
Шаг 2. Очистка
# Удаляем дубликаты
df = df.drop_duplicates()
# Заполняем пропуски
df["salary"] = df["salary"].fillna(df["salary"].median())
# Фильтруем выбросы
df = df[df["age"].between(0, 120)]
Шаг 3. Приведение форматов
df["signup_date"] = pd.to_datetime(df["signup_date"], errors="coerce")Шаг 4. Масштабирование
Шаг 4. Масштабирование
scaler = StandardScaler()
df[["age", "salary"]] = scaler.fit_transform(df[["age", "salary"]])
Шаг 5. Проверка результата
assert df["user_id"].notna().all()
На этом этапе у вас уже есть рабочая логика подготовки данных. Но пока она существует только в виде набора ручных действий.
Автоматизированная предобработка: переход в продакшен
Ручной режим перестаёт работать, как только наступает одно из условий:
-
данные обновляются регулярно;
-
появляется модель или отчёт;
-
процесс нужно повторять.
Теперь задача — сделать процесс воспроизводимым.
Как выглядит автоматизация
Те же шаги оформляются в функцию:
def preprocess_users(df: pd.DataFrame) -> pd.DataFrame:
df = df.copy()
# Очистка
df = df.drop_duplicates()
df["salary"] = df["salary"].fillna(df["salary"].median())
df = df[df["age"].between(0, 120)]
# Преобразование
df["signup_date"] = pd.to_datetime(df["signup_date"], errors="coerce")
return df
Теперь код можно переиспользовать, результат воспроизводим, ошибки легче отлаживать.
Следующий уровень: полноценный пайплайн
Пример:
def full_pipeline(df: pd.DataFrame) -> pd.DataFrame:
df = preprocess_users(df)
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df[["age", "salary"]] = scaler.fit_transform(df[["age", "salary"]])
return df
Как понять, что пора автоматизировать
Автоматизация — уже не опция, а необходимость, если выполняется хотя бы одно из условий:
-
данные обновляются регулярно;
-
вы повторяете одни и те же шаги;
-
результат влияет на бизнес-решения;
-
есть модель или отчёт в проде.
Ручная предобработка отвечает на вопрос: «Что нужно сделать с данными?»
Автоматизированная — на вопрос: «Как делать это стабильно каждый раз?»
Если у вас есть только первый этап — у вас прототип. Если есть оба — у вас система.
Частые ошибки при подготовке данных
Собрал ошибки, которые встречаются чаще всего, — и советы, что делать вместо них. Этот блок удобно читать как короткий чек-лист перед релизом или передачей данных в модель.
1. Удаляем строки без понимания последствий
В чём ошибка: строки с пропусками или аномалиями удаляют автоматически просто потому, что так проще.
Чем это опасно: можно случайно выкинуть важный сегмент данных и исказить картину.
Что делать вместо этого: сначала понять, почему появились пропуски, и только потом выбирать стратегию: удаление, заполнение или отдельная обработка.
2. Заполняем пропуски по умолчанию, не глядя на распределение
В чём ошибка: импутация делается механически — средним, медианой или константой — без проверки, подходит ли это для конкретного признака.
Чем это опасно: можно сместить распределение и ухудшить качество анализа или модели.
Что делать вместо этого: сначала посмотреть распределение признака и понять, насколько выбранный способ заполнения искажает данные.
3. Игнорируем логические противоречия
В чём ошибка: данные проверяются только на формальные ошибки, но не на здравый смысл и бизнес-логику.
Чем это опасно: в наборе могут остаться записи вроде отрицательного возраста, невозможной даты или несогласованных статусов.
Что делать вместо этого: добавлять бизнес-валидацию — проверять не только типы и диапазоны, но и смысловые ограничения.
4. Работаем «на глаз» без повторяемого процесса
В чём ошибка: очистка делается вручную, по месту, без скриптов и без фиксированной логики.
Чем это опасно: процесс нельзя воспроизвести, а значит, нельзя нормально обновить данные или отладить результат.
Что делать вместо этого: оформлять подготовку данных в виде кода или пайплайна, чтобы любой шаг можно было повторить.
5. Не сохраняем исходную версию данных
В чём ошибка: работа идёт только с одной копией датасета.
Чем это опасно: если что-то пошло не так, откатиться уже некуда.
Что делать вместо этого: всегда хранить raw-версию отдельно и вести версии после каждого этапа подготовки.
6. Не документируем, что именно сделали с данными
В чём ошибка: очистка и преобразования выполняются, но без описания правил и причин.
Чем это опасно: другой человек не сможет понять логику изменений, а вы сами через неделю не вспомните, почему приняли именно такое решение.
Что делать вместо этого: коротко фиксировать, какие правила применялись, что удалили, что заполнили и почему.
7. Не проверяем результат после очистки
В чём ошибка: данные почистили, но не посмотрели, как изменились ключевые метрики и распределения.
Чем это опасно: можно случайно испортить данные и не заметить этого до этапа анализа или обучения.
Что делать вместо этого: после каждого важного шага пересчитывать основные метрики, смотреть распределения и сравнивать данные до и после.
8. Проверяем данные только в конце
В чём ошибка: контроль качества оставляют на последний шаг.
Чем это опасно: ошибки накапливаются по ходу всего процесса, и в конце их уже сложнее разбирать.
Что делать вместо этого: проверять данные поэтапно: после загрузки, после очистки, после преобразования и перед передачей в анализ.
Резюмируем
Хорошая аналитика начинается не с моделей и не с визуализаций. Она начинается с честного ответа на вопрос: можно ли этим данным доверять.
Исправить тип столбца, удалить дубликаты, заполнить пропуски по правилу, а не по умолчанию — каждое из этих действий стоит минут, но экономит часы отладки и недели переделок. Подготовка данных — это не служебная часть проекта. Это фундамент, на котором держится всё остальное.
А вы проверяете данные до анализа или уже после того, как что-то пошло не так?
Интересно почитать реальные кейсы в комментариях ↓
Чтобы расти, нужно выйти из привычной зоны и сделать шаг к переменам. Можно изучить новое, начав с бесплатных материалов:
-
практического гайда «ИИ вместо переработок: как освободить 20+ часов в неделю»;
-
совместного с Zigmund.Online курса «Карьера без страха»;
-
воркшопа «1C-аналитик: погружение в профессию на практике»;
-
практического курса «Обучение основам работы в Figma с нуля»;
-
вводного курса магистратуры НИУ ВШЭ «Инженерия данных».
Или можно стать востребованным сотрудником и открыть открыть бóльшие перспективы в карьере с профессиональным обучением:
-
на программе повышения квалификации «Python для анализа данных»;
-
на курсе «Продвинутый SQL»;
-
на программе профессиональной переподготовки «Аналитика данных», которая разработана совместно с МФТИ;
-
на курсе «Специалист по искусственному интеллекту»;
-
в магистратуре НИУ ВШЭ «Инженерия данных».
Автор: Mr_Manro


