Статья Автор: Деникина Н.В., Деникин А.В.

Ремонт без подмены фактов

Ремонт без подмены фактов

Если очистить небольшой файл один раз вручную, результат может выглядеть вполне убедительно. Проблема появляется через неделю, когда приходит новая версия данных и нужно вспомнить: какие пробелы мы заменяли, где убирали пробелы в строках, почему часть значений превратилась в NaN и в каком порядке всё это происходило.

В этот момент предобработка превращается из набора приёмов в воспроизводимый процесс. Хороший процесс можно запустить снова на тех же данных и получить тот же результат. А если правила изменились, можно увидеть, что именно изменилось вместе с ними.

Хорошая обработка данных оставляет след Исходные данные df_original clean_heroes() строки · типы · пропуски диапазоны · дубликаты одни и те же правила → воспроизводимый результат df_clean обработанные данные audit что изменилось и в каком объёме Исходник сохраняется — результат всегда можно сравнить с ним
Функция как запись решения
def clean_heroes(df, current_year=2026):
    out = df.copy()

    # здесь идут обоснованные преобразования

    return out, audit

Функция начинает с копии, поэтому исходная таблица не портится. На выходе удобно вернуть не только очищенные данные, но и небольшой журнал audit: что было обнаружено и как изменился набор.

Порядок действий имеет значение. Маркер "unknown" сначала нужно распознать как отсутствие значения — только после этого его увидит проверка пропусков. Две строки могут стать полным дублем только после нормализации пробелов и регистра. Невозможный год обнаружится лишь после того, как столбец удалось преобразовать в число.

Поэтому универсальной «правильной очереди» на все случаи нет. Есть более важный принцип: каждый следующий шаг должен опираться на уже понятное состояние данных, а не на случайный порядок команд в notebook.


Какой порядок лучше отражает воспроизводимую обработку данных, если мы хотим сохранить возможность проверить каждое решение?


Журнал изменений нужен не для отчётности
audit = {
    "rows_before": len(df),
    "rows_after": len(out),
    "full_duplicates_before": int(df.duplicated().sum()),
    "missing_after": out.isna().sum().to_dict()
}

По такому журналу можно быстро восстановить последствия обработки: сколько строк было до и после, были ли полные повторы, какие пропуски остались. В реальном проекте набор полей будет зависеть от задачи, но идея одна: значимые изменения не должны исчезать внутри длинного кода.

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

Но даже аккуратная функция и подробный журнал ещё не доказывают, что итоговая таблица корректна. Для этого нужны проверки, которые способны остановить нас, если какое-то обещание о данных нарушилось.

Перейти к лаборатории «Спасти базу супергероев» →

Печать