我正在使用code exercises的一组Yelp reviews dataset。现在,在练习中,我应该读入review.json,每行有一个JSON记录。我制作了一个较小版本的JSON文件,仅进行100条记录用于测试。
我可以将整个测试文件读入pandas数据框中并进行检查。
但是,完整的数据集文件大约有600万行。建议使用chunksize并构建一个json阅读器。即使使用测试输入,我也会遇到错误。
我的代码当前看起来像这样
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 user guide中引用的我得到一个错误:
ValueError: Unexpected character found when decoding 'false'
更新-已建议该问题是由数据文件中嵌入(引号)“ \ n”字符引起的;大熊猫看到的JSON记录不是每行一条,而是多行。
这种情况下,错误消息非常不透明。另外,如果有600万行,我该如何告诉pd.read_json
忽略"\n"
而仅查看数据中的实际换行符?
更新
建议如果我修复我的错字(本文中是错字,而不是我的代码中的错字),并使用Unix文件路径而不是URL(JSON无关紧要:请参阅文档)。 / p>
当我这样做但保留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"}
答案 0 :(得分:0)
首先,您的
path 'file://localhost/Users/.../DSC_Intro/'
无效的python代码。如果尝试以这种方式执行该操作,则会收到无效的语法错误。那么,我假设这只是显示path变量的值。我不知道这些省略号是文字上的,还是您的环境截断path
的显示结果。我在这里假设您的路径是系统的有效文件URL,因为在这里考虑错误的路径似乎并不重要。
无论哪种方式,是的,read_json
可以一口气读取文件URL,就像您在其中指定的那样(我在那里学到了东西),它可以从文件URL中读取json:
pd.read_json(fname, lines=True)
但是,如果您尝试通过指定此内容来创建阅读器,则
pd.read_json(fname, lines=True, chunksize=...)
那么你就得到
TypeError: sequence item 0: expected str instance, bytes found
第二,是的,用StringIO包装类似文件的参数可以使该错误消失,但是由于您可能认为的任何原因都无法解决问题,它的使用是基于对您指向的熊猫文档的误读。 / p>
我将在此处引用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)
换句话说,它们通过StringIO()包装JSON字符串,而不是路径。这只是出于记录示例的目的,因此您可以看到如果您将JSON字符串当作从文件中读取一样对待,则可以成批读取。那就是StringIO()所做的。因此,当您将描述文件URL的字符串包装在StringIO()中时,我希望read_json
然后尝试将该字符串解释为正在从文件读取的JSON并进行解析。可以理解,它不是JSON,因此会失败。
这使我们回到为什么read_json
无法分块读取文件URL的原因。我对此没有立即好的答案。我怀疑这取决于read_json
如何打开文件URL的内部结构,或者它是基于什么功能。如果您打算或被迫从文件URL进行分块,那么我怀疑您是在控制打开文件的模式,或者也许以某种方式为read_json
提供了明确的指导解释它得到的字节流。我不确定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)
我敢打赌,它按预期工作! (它对我来说一如既往)。 注意:Windows不使用正斜杠路径定界符,以上述方式通过串联字符串构造路径可能很脆弱,但是通常如果使用“适当的”正斜杠定界符(微笑),那么体面的语言就会内部理解这一点。它使用反斜杠构造路径,这肯定会引起您的痛苦。但是请注意这一点。