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

Числа в маскировке

Числа в маскировке

Человек видит 42 и почти автоматически думает о числе. В CSV это всего лишь последовательность символов, пока библиотека не решит, каким типом её считать. Достаточно одной записи unknown, чтобы весь столбец оказался текстовым.

Что делает pd.to_numeric(..., errors="coerce") "85" "unknown" pd.to_numeric errors="coerce" 85 NaN Плохая строка не исчезает: она превращается в явный пропуск, который можно обработать осознанно

Для аккуратного файла можно использовать жёсткое преобразование вроде astype(int). В грязных данных оно часто останавливается на первой неподходящей записи. Поэтому полезен более диагностический подход:

df["power"] = pd.to_numeric(
    df["power"],
    errors="coerce"
)

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

Формат числа тоже бывает частью проблемы

Стоимость 10,000,000 может храниться строкой только из-за разделителей тысяч. Тогда сначала убирают оформление, а уже потом меняют тип.

cost = (
    df["costume_cost"]
      .astype("string")
      .str.replace(",", "", regex=False)
)

df["costume_cost"] = pd.to_numeric(
    cost,
    errors="coerce"
)
Правильный тип ещё не гарантирует правильный смысл

Самые неприятные ошибки вообще не связаны с типами. Представьте столбец расстояний: большинство значений лежит от 1 до 15, а из одного источника регулярно приходят 2500–9000. Все записи числовые, поэтому pandas спокойно посчитает среднее. Но если одна система присылала метры, а остальные — километры, математически корректный расчёт окажется бессмысленным.

print(
    df.groupby("source_system")["distance_km"]
      .describe()
)

Такие значения нельзя исправлять только по принципу «слишком большие». Нужно предметное основание: описание столбца, документация источника или отчётливая закономерность в способе сбора. Иначе деление на 1000 будет просто красивой догадкой.


В distance_km большинство значений лежит между 1 и 15, но из одного источника регулярно приходят числа 2500–9000. По паспорту столбец хранится в километрах. Какой следующий шаг лучше?


Невозможное число лучше сделать явным

Вернёмся к шкале power от 1 до 100. Если в ней встретилось 130, мы знаем, что правило нарушено, но не знаем истинного значения. Очень соблазнительно «починить» его функцией clip(1, 100) и получить 100. Проблема в том, что 100 никто не наблюдал — это число создали мы сами.

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

С датами действует та же логика

first_appearance = 1963 — это просто год, ему достаточно числового типа. Но если в таблице хранится полная календарная дата, строка вроде 1963-03-01 должна стать настоящей датой:

dates = pd.to_datetime(
    df["event_date"],
    errors="coerce"
)

Некорректная запись превратится в NaT — аналог пропуска для даты. И снова после преобразования нужно посмотреть, сколько значений не удалось разобрать. Смена типа — это не финал, а ещё один этап диагностики.


Что лучше сделать с power = 130, если допустимый диапазон 1–100, но истинное число неизвестно?


Мы разобрали отдельные источники проблем: пропуски, повторяющиеся записи, строки, числа, диапазоны и единицы. В реальной работе они редко встречаются по одному. Теперь соберём эти решения в процесс, который можно повторить на следующей версии файла.

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

Загрузка...
Чтобы оставить комментарий, необходимо авторизоваться
💬
Пока нет комментариев. Будьте первым!
Печать