Загрузка файла CSV с двоичными данными в pandas - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь проанализировать файл CSV (из внешнего источника данных), где в одном из столбцов используются несовместимые кодировки символов. Вместо того, чтобы пытаться заставить поставщика данных использовать согласованную кодировку, я хотел бы просто прочитать этот столбец как двоичные данные. Однако pandas.read_csv, кажется, декодирует весь файл в строку перед синтаксическим анализом, так что это дает мне ошибки (UnicodeDecodeError). Вот пример игрушки (python 3):

>>> from io import BytesIO
>>> import pandas as pd
>>> csv = b'Encoding,Data\nascii,abc\nwindows-1252,\xae\nutf-8,\xe2\x80\x9c1\xe2\x80\x9d\n'
>>> pd.read_csv(BytesIO(csv))
Traceback (most recent call last):
  File "pandas/_libs/parsers.pyx", line 1130, in pandas._libs.parsers.TextReader._convert_tokens
  File "pandas/_libs/parsers.pyx", line 1254, in pandas._libs.parsers.TextReader._convert_with_dtype
  File "pandas/_libs/parsers.pyx", line 1269, in pandas._libs.parsers.TextReader._string_convert
  File "pandas/_libs/parsers.pyx", line 1459, in pandas._libs.parsers._string_box_utf8
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae in position 0: invalid start byte

Я хотел бы получить результат, эквивалентный следующему:

>>> df = pd.DataFrame({'Encoding': ['ascii','windows-1252','utf-8'],
...                    'Data': [b'abc',b'\xae',b'\xe2\x80\x9c1\xe2\x80\x9d']})
>>> df
       Encoding                          Data
0         ascii                        b'abc'
1  windows-1252                       b'\xae'
2         utf-8  b'\xe2\x80\x9c1\xe2\x80\x9d'

Который (в этом примере с игрушкой) мог бы быть обработан следующим образом: это:

>>> df.apply(lambda row: str(row.Data,row.Encoding), axis=1)
0    abc
1      ®
2    “1”
dtype: object

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

1 Ответ

2 голосов
/ 24 апреля 2020

По словам Сержа Баллеста , отвечающего на этот пост

"Pandas, позволяет указать кодировку, но не позволяет игнорировать ошибки, чтобы не заменять автоматически обидчика байт. Таким образом, не существует одного размера, подходящего для всех методов , но по-разному в зависимости от фактического варианта использования. "

  1. Итак, сначала попробуйте использовать кодировку Latin1, потому что он принимает любой возможный байт в качестве ввода и может быть достаточным в зависимости от вашего варианта использования (я мог бы запустить ваш игрушечный пример, используя это):

    data_frame = pd.read_csv(BytesIO(csv), encoding="latin1"))
    
  2. Как указано в ответе Сержа: " Pandas не предусматривает специальной обработки ошибок, но функция Python open имеет (при условии Python3), а read_csv принимает файл как объект. " В вашем случае вы можете рассмотреть возможность использования 'backslashreplace', который заменяет ошибочные байты на escape-последовательность их Python с обратной косой чертой:

    file_encoding = 'utf8'        # set file_encoding to the file encoding (utf8, latin1, etc.)
    with open(path_to_csv, encoding=file_encoding, errors = 'backslashreplace') as my_csv:
      dataframe = pd.read_csv(my_csv)
    
...