ValueError Чтение большого набора данных с помощью pd.read_json - PullRequest
1 голос
/ 24 июня 2019

Я работаю над набором кодовых упражнений , в которых используется Набор данных отзывов Yelp .На этом этапе упражнений я должен прочесть в review.json, в котором по одной записи JSON на строку.Для тестирования я создал уменьшенную версию файла JSON, содержащую только 100 записей.

Я могу прочитать весь тестовый файл в фрейме данных pandas и проверить его.

Полный файл набора данныхОднако около 6 миллионов строк.Рекомендуется использовать chunksize и собрать JSON Reader.Я сталкиваюсь с ошибками, даже с моим тестовым вводом.

Мой код в настоящее время выглядит так

path = 'file://localhost/Users/.../DSC_Intro/'
filename = path + 'yelp_dataset/review_100.json'

# create a reader to read in chunks
review_reader = 
pd.read_json(StringIO(filename), lines=True, chunksize=10)

type(review_reader)

Вызов типа возвращает

pandas.io.json.json.JsonReader

, что выглядит хорошо.

Затем я пытаюсь

for chunk in review_reader:
    print(chunk)

, как указано в Руководстве пользователя pandas , и я получаю ошибку:

ValueError: Unexpected character found when decoding 'false'

full error output

Обновление - было высказано предположение, что проблема вызвана встроенными (цитируемыми) символами "\ n" в файле данных;что панды видят записи JSON не по одной, а по нескольким строкам.

Сообщение об ошибке ОЧЕНЬ непрозрачно, если это так.Кроме того, с 6 миллионами строк, как я должен сказать pd.read_json игнорировать "\n" и смотреть только фактические новые строки в данных?

Обновление

Это былопредложил исправить ошибку (это опечатка в этом сообщении, а не опечатка в моем коде) и использовать путь к файлу Unix вместо URL (JSON это не волнует: см. документы).

Когда я делаю это, но сохраняю StringIO (), я получаю другую ValueError.

Когда я делаю это, но удаляю StringIO (), код работает.

Это кажется очень хрупким.: - (


Примечание В руководстве есть ключ ответа. Я пробовал этот код. Ключ ответа использует

review_reader = 
pd.read_json(filename, lines=True, chunksize=10)

, который вызывает ошибку TypeError

sequence item 0: expected str instance, bytes found

Добавление StringIO(), похоже, решило эту проблему.

Ввод Пример записи JSON, по одной на строку входного файла.

{"review_id":"Amo5gZBvCuPc_tZNpHwtsA","user_id":"DzZ7piLBF-WsJxqosfJgtA","business_id":"qx6WhZ42eDKmBchZDax4dQ","stars":5.0,"useful":1,"funny":0,"cool":0,"text":"Our family LOVES the food here. Quick, friendly, delicious, and a great restaurant to take kids to. 5 stars!","date":"2017-03-27 01:14:37"}

1 Ответ

0 голосов
/ 29 июня 2019

Во-первых, ваш

path 'file://localhost/Users/.../DSC_Intro/'

не является допустимым кодом Python. Если вы попытаетесь выполнить это как таковое, вы получите неверную синтаксическую ошибку. Я предполагаю, что это просто показывает значение переменной пути. Я не знаю, являются ли эти эллипсы буквальными или результатом того, что ваша среда усекает отображение path. Здесь я предполагаю, что ваш путь является допустимым URL-адресом файла для вашей системы, поскольку здесь не совсем уместно рассматривать неправильный путь.

В любом случае, да, read_json может прочитать json из URL-адреса файла, как вы указали там (я узнал кое-что там), если вы прочитаете его за один раз:

pd.read_json(fname, lines=True)

Но если вы попытаетесь создать читателя из этого, указав

pd.read_json(fname, lines=True, chunksize=...)

тогда вы получите

TypeError: sequence item 0: expected str instance, bytes found

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

Я процитирую пару битов из read_json документа здесь:

Подпись: pd.read_json ( path_or_buf = Нет, ...

path_or_buf: допустимая строка JSON или подобная файлу, по умолчанию: нет Строка может быть URL. Допустимые схемы URL включают http, ftp, s3, gcs и файл. Для файловых URL-адресов ожидается хост. Например, местный файл может быть file://localhost/path/to/table.json

Таким образом, с помощью read_json вы можете либо указать ему действительную строку, которая является допустимым JSON, либо вы можете присвоить ему файлоподобный объект, который указывает на файл, содержащий JSON.

Обратите внимание на документы панд, которые вы цитируете:

In [258]: jsonl = '''
   .....:     {"a": 1, "b": 2}
   .....:     {"a": 3, "b": 4}
   .....: '''
   .....: 

- это JSON, а не путь. Когда их пример тогда делает:

df = pd.read_json(jsonl, lines=True)

это просто анализ JSON в строке - здесь нет файлов. Когда он хочет продемонстрировать чтение из файла кусками, он делает

# reader is an iterator that returns `chunksize` lines each iteration
In [262]: reader = pd.read_json(StringIO(jsonl), lines=True, chunksize=1)

Другими словами, они обертывают строку JSON, а не путь, с помощью StringIO (). Это только для целей документированного примера, поэтому вы можете видеть, что если вы обрабатывали строку JSON так, как если бы она читалась из файла , вы можете читать ее порциями. Вот что делает StringIO (). Поэтому, когда вы переносите строку, описывающую URL вашего файла, в StringIO (), я ожидаю, что read_json затем пытается интерпретировать эту строку как JSON, которая читается из файла, и анализировать ее. Это понятно, потому что это не JSON.

Это возвращает нас к тому, почему read_json не может прочитать URL вашего файла в виде фрагментов. У меня нет немедленного хорошего ответа на это. Я подозреваю, что во внутренних принципах read_json открывается URL-адрес файла или какая функция лежит в основе этого. Если вы намеревались или были вынуждены выполнить эту порцию по URL-адресу файла, то я подозреваю, что вы будете стремиться контролировать режим, в котором открывается файл, или, возможно, каким-то образом дать четкое указание read_json, как интерпретировать bytestream это получает. Библиотеки, такие как urllib2, могут быть полезны здесь, я не уверен.

Но давайте вернемся к лучшему исправлению здесь. Почему мы пытаемся указать путь в виде URL файла? Просто укажите ваш путь в качестве пути ОС, например,

path = '/path/to/my/data/'

, а затем

filename = path + 'yelp_dataset/review_100.json'

# create a reader to read in chunks
review_reader = pd.read_json(filename, lines=True, chunksize=10)

И я уверен, что это работает как задумано! (Это для меня, как всегда). Предостережение: окна не используют разделители прямого слэша, и построение путей путем конкатенации строк описанным выше способом может быть хрупким, но обычно, если вы используете «правильные» разделители прямого слэша (улыбка), приличные языки внутренне это понимают. Он строит пути, используя обратную косую черту, которая гарантированно причинит вам боль. Но просто следите за этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...