Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Очистка данных в pandas: пропуски, дубликаты, типы

Очистка данных в pandas: рабочий порядок от сырого файла до пригодного датасета

Системный пайплайн очистки данных в pandas: диагностика качества, пропуски NA, дубликаты, приведение типов, даты и строки, выбросы — с порядком операций и типовыми ошибками.

Прямой ответ

Очистка данных — не набор приёмов, а порядок операций, и он важнее отдельных функций. Рабочий пайплайн из семи шагов: диагностика (что вообще не так) → структура (колонки, имена, лишние строки-заголовки) → типы (числа числами, даты датами) → пропуски (стратегия по каждой колонке) → дубликаты (полные и смысловые) → строки (регистр, пробелы, категории) → фиксация (сохранение очищенного в parquet + код пайплайна в репозиторий). Главная ошибка новичков — начинать с заполнения пропусков до приведения типов: «числа с прочерками» чинятся иначе, чем настоящие NA, и порядок решает.

Шаг 1. Диагностика: пятиминутный осмотр

До любых правок — три команды, которые задают всю дальнейшую работу. df.info() показывает типы и число непустых значений по колонкам — сразу видно, где «числа» читались как текст. df.isna().mean().sort_values(ascending=False) — доля пропусков по колонкам: колонки с 80%+ пропусков — кандидаты на удаление целиком. df.describe(include='all') — распределения и «странные» категории; для строк отдельно df['col'].value_counts().head(20) — опечатки и варианты написания видны в первых строках. Сюда же быстрая проверка на дубли: df.duplicated().sum(). Результат осмотра стоит зафиксировать текстом (в ноутбуке — markdown-ячейкой): через неделю вы не вспомните, что именно считали «грязью».

Шаг 2–3. Структура и типы: фундамент

Структурные проблемы лечатся до содержательных: лишние строки-заголовки внутри данных (skiprows при чтении или df.iloc[1:]), колонки-индексы без имени, «широкий» формат, который надо развернуть в «длинный» (pd.melt) — и обратно для отчётности (pivot_table). Приведение типов — следующий обязательный этап: pd.to_numeric(col, errors='coerce') превращает мусор в NA осознанно (до этого посмотрите, что именно не парсится: col[pd.to_numeric(col, errors='coerce').isna()].unique() — часто там «1 234,56» с неразрывными пробелами, лечится одной заменой). Даты — только pd.to_datetime с явным format= (без него pandas угадывает и молча путает день с месяцем на европейских датах). Категории — astype('category') для строк с малым числом значений: экономия памяти в разы, что на больших файлах критично.

Шаг 4. Пропуски: стратегия вместо fillna «на глаз»

Заполнение пропусков — решение предметное, и принимается по колонке. Удаление строк (dropna) допустимо, когда пропусков мало и они случайны; удаление колонок — когда данных в них почти нет. Заполнение константой («нет данных» для категориальных) или медианой (для skewed-числовых; среднее искажается выбросами) — рабочие варианты с явной пометкой флагом was_missing. Forward-fill (ffill) осмыслен только для временных рядов. Опасный антипаттерн — заполнение пропусков до обучения модели без флага: модель не узнает, что признак был синтетическим. И правило для честности: доля заполненного выше 20–30% — это уже новый признак, и выводы на нём требуют осторожности.

Шаг 5–6. Дубликаты и строки

Дубликаты бывают двух видов, и лечатся по-разному. Полные (df.duplicated()) — удаляются молча после проверки, что дубль действительно технический (экспорт дважды). Смысловые — та же сущность с вариациями (заказ с опечаткой в id клиента): требуют ключа нормализации и решения, какую запись считать истинной (по дате обновления, по полноте). Строковая гигиена — дешёвый выигрыш: str.strip() (пробелы, включая неразрывные), str.lower() для сравнений, унификация вариантов через отображение словарём (не регулярками в лоб — приёмы безопасной работы с паттернами важны и здесь), и категоризация после унификации. Отдельный класс — «ложные строки» в числовых колонках («н/д», «-», «нет»): их приводят к NA на этапе типов, не после.

Шаг 7. Фиксация: пайплайном, не руками

Очищенный датасет без кода очистки — полуфабрикат: при обновлении выгрузки всё придётся делать заново. Практика: пайплай живет в .py-скрипте или параметризованном ноутбуке (функция clean(df) -> df), результат кладётся в parquet (типы сохраняются, объём в разы меньше CSV), рядом — короткий README «что сделано и почему». Контроль качества после обновления выгрузки — дешёвые ассерты: число строк в ожидаемом диапазоне, доля NA по ключевым колонкам ниже порога, уникальность ключа. При таком подходе «грязные данные» перестают быть еженедельным приключением. Для файлов больше памяти подход тот же, но потоково — приёмы из статьи про Jupyter и большие данные; требования к железу под тяжёлую очистку — в материале про стек аналитика.

Типовые ошибки, которые стоят часов

Первая — очистка «по месту» без копий и логов: через день непонятно, что изменено; лечится версионированием шагов (или хотя бы последовательными присваиваниями с явными именами). Вторая — SettingWithCopyWarning игнорируется, а зря: это сигнал, что вы правите фрагмент, а не датасет (лечится явным .loc или .copy()). Третья — очистка до понимания предметки: «аномалия» в 10 000 может быть валидным оптовым заказом, и её удаление испортит анализ хуже пропуска. Четвёртая — смешение очисток разных выгрузок в один скрипт без параметров: вторая выгрузка приезжает с новой «грязью», и пайплайн ломается в тихом месте. Порядок «диагностика → решение → фиксация» защищает от всех четырёх.

FAQ

С чего начать, если данных «очень много и они ужасные»? С одной репрезентативной выборки (1–5%): весь пайплайн очистки отлаживается на ней за минуты, затем применяется к полному объёму. Править полный файл итеративно — способ провести день в ожидании.

Когда очистка в pandas, а когда в SQL? Если данные уже в БД — структурные операции (фильтры, джойны, агрегации) дешевле сделать там, а pandas оставить для сложной логики и финальной формы. Дублирование одной и той же очистки в двух местах — источник расхождений.

Как понять, что пропуски «случайные»? Сравните распределения других колонок для строк с пропуском и без (groupby по флагу was_missing + describe): заметные отличия означают систематичность — такие пропуски несут информацию и требуют флага, а не заполнения.

Стоит ли очищать данные «про запас»? Нет: очистка следует за задачей. Универсального «чистого датасета» не существует — для одной задачи колонка-мусор, для другой ключевая; пайплайн параметризуется под конкретное использование.

Источники: руководство пользователя pandas (missing data, basics, text) — ссылки в шапке.