Найти тему
Властелин машин

Фантомные ошибки обработки файлов с Python

Оглавление

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

Изучение вопроса проведем на примере сгенерированного игрушечного набора data (код представлен в конце статьи) о заработке людей из разных городов (идентифицируются по индексу) следующего вида:

Некорректное распознавание строк

Поле "индекс_города" состоит из семи случайных цифр от 0 до 9, которые в некоторых случаях разделяются символами "/" или "-". После сохранения data в файл и загрузки обратно в df не все значения этого поля корректно распознаются. Например, при выдаче длин строк в ячейках "индекс_города" (всего 100) получаем следующее:

-2

Найдем значения, длины которых не распознаны:

-3

Похоже не распознаны строки с индексами, которые выглядят как числа (то есть не разделены "/" или "-"). Для борьбы с эти следует явно привести столбец к строчному типу:

df['индекс_города'] = df['индекс_города'].astype(str)

Теперь повторно получим длины строк в ячейках "индекс_города" :

-4

Строки из цифр, начинающихся с нуля

То же поле "индекс_города" после сохранения сгенерированных данных в файл и загрузки в таблицу df предоставляет очередной сюрприз. В частности, появляется индекс города, содержащий только 6 символов, что видно из предыдущей картинки.

-5

Оказывается, в первоначальной таблице содержался индекс 0319966, который после сохранения в Excel таблицу и загрузки обратно потерял первый символ. Вероятно, это обусловлено тем фактом, что текстовый процессор воспринимает последовательность цифр как число и не видит смысла в начальном 0. Для справки, если вы попытаетесь в Microsoft Excel или Google Таблицах сохранить в ячейке аналогичную последовательность символов, то 0 будет потерян.

Проблема решается путем чтения файлов функциями Pandas (read_excel или read_csv ) с параметром dtype ='str' . Кстати, этим же способом можно решить и первую проблему.

Числа с плавающей точкой

Поле "зарплата " также заставляет нас помучиться. В частности, процедура выгрузки-загрузки данных приводит к изменениям в количестве сохраняемых символов после запятой. Однако установить это не так просто. Попытаемся вывести все значения зарплаты, которые не совпадают у одних и тех же людей:

-6
-7

Различия не визуализируются, кажется, что сохранение происходит до 4 символа. Однако, если вывести эти же данные в командную строку, получим другой результат:

-8

Если же просмотреть файл с данными, то получим "третью" версию точности сохранения:

-9

Мораль из этого проста - перед сохранением округляем данные до требуемой точности:

data['зарплата'] = np.round(data['зарплата'],2)

Теперь расхождений не будет:

-10

Таким образом, можно сделать следующие выводы:

  1. в определенных случаях читаем файлы с параметром dtype ='str' и явно приводим поля к соответствующим им типам;
  2. перед сохранением значений с плавающей точкой, округляем их.

Ниже привожу код для генерации данных:

-11
-12

Код можно скопировать в удобном виде с моей страницы в teletype.in.

-13

Наука
7 млн интересуются