加快将 json 数据加载到数据框中

Posted

技术标签:

【中文标题】加快将 json 数据加载到数据框中【英文标题】:Speed Up Loading json data into dataframe 【发布时间】:2018-04-07 00:43:24 【问题描述】:

我正在尝试使用下面的代码将一组非常大的嵌套 json 文件读入 pandas 数据帧。这是几百万条记录,它是来自 yelp 学术数据集的“评论”文件。

有人知道更快的方法吗?

是否可以只加载 json 记录的样本?我可能只需要几十万条记录就可以了。

另外,我可能不需要 review.json 文件中的所有字段,我可以只加载其中的一个子集,例如 user_id、business_id、stars 吗?那会加快速度吗?

我会发布示例数据,但我什至无法完成加载。

代码:

df_review = pd.read_json('dataset/review.json', lines=True)

更新:

代码:

reviews = ''

with open('dataset/review.json','r') as f:
    for line in f.readlines()[0:1000]:
        reviews += line

testdf = pd.read_json(reviews,lines=True)

错误:

---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
<ipython-input-18-8e4a45990905> in <module>()
      5         reviews += line
      6 
----> 7 testdf = pd.read_json(reviews,lines=True)

/Users/anaconda/lib/python2.7/site-packages/pandas/io/json.pyc in read_json(path_or_buf, orient, typ, dtype, convert_axes, convert_dates, keep_default_dates, numpy, precise_float, date_unit, encoding, lines)
    273         # commas and put it in a json list to make a valid json object.
    274         lines = list(StringIO(json.strip()))
--> 275         json = u'[' + u','.join(lines) + u']'
    276 
    277     obj = None

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 357: ordinal not in range(128)

更新 2:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

reviews = ''

with open('dataset/review.json','r') as f:
    for line in f.readlines()[0:1000]:
        reviews += line

testdf = pd.read_json(reviews,lines=True)

【问题讨论】:

【参考方案1】:

加速那条线将是一项挑战,因为它已经超级优化了。

我会首先检查您是否可以从提供者那里获得更少的行/数据,正如您所提到的。

如果您之前可以处理数据,我建议您先将其转换为 JSON(甚至尝试不同的解析器,它们对每个数据集结构的性能都会发生变化),而不是只保存您需要的数据,并使用此输出调用 pandas方法。

Here你可以找到一些json解析器的基准,记住你应该对你的数据进行测试,这篇文章是2015年的。

【讨论】:

【参考方案2】:

如果您的文件按照您的暗示将 json 对象行分隔,这可能会起作用。只需读取文件的前 1000 行,然后使用 pandas 读取。

import pandas as pd  

reviews = ''

with open('dataset/review.json','r') as f:
    for line in f.readlines()[0:1000]:
        reviews += line

pd.read_json(reviews,lines=True)

【讨论】:

这行不通,因为它会破坏 json 格式。 @OrDuan 我同意,但最初的问题包括“lines=True”,这意味着 json 的格式设置为每行都是不同的 json 对象。如果是这种情况,上述解决方案应该可以工作。 @NathanH 感谢您这么快回复我。我尝试了您的建议并收到一条错误消息。我添加了我运行的代码和错误消息作为对原始帖子的更新。你知道问题可能是什么吗?还使用您的建议,我可以读取一组记录而不是整个文件吗?是这个主意吗? @user3476463 你能发布一个json结构的例子吗?这在试图解决这个问题时会有所帮助。另外,你能不能直接打开json文件,把一些对象复制到一个新文件中,然后处理这个文件? @NathanH 一旦我将默认编码设置为 utf-8,我就可以使用您的建议从 json 文件中导入一些记录,谢谢!如果我想发布 json 数据的样本,我该如何打开它并获取一些?我之前尝试将文件放入文本编辑器,但它太大了,它只是锁定了文本编辑器。有没有办法在python中做到这一点?【参考方案3】:

我同意@Nathan H 的提议。但确切的点可能在于并行化。

import pandas as pd  
buf = ''
buf_lst = []
df_lst = []
chunk_size = 1000
with open('dataset/review.json','r') as f:
    lines = f.readlines()
    buf_lst += [ ''.join(lines[x:x+chunk_size]) for x in range(0,len(lines), chunk_size)]

def f(buf):
    return pd.read_json( buf,lines=True)

#### single-thread
df_lst = map( f, buf_lst)

#### multi-thread
import multiprocessing as mp
pool = mp.Pool(4)
df_lst = pool.map( f, buf_lst)
pool.join()
pool.close()

但是,我还不确定如何组合 pandas 数据框。

【讨论】:

我希望你已经知道了,但是 pandas.concat(list_of_frames) 是你想要组合它们的东西

以上是关于加快将 json 数据加载到数据框中的主要内容,如果未能解决你的问题,请参考以下文章

如何将 json 加载到 pandas 数据框中?

无法将完整数据从 json 文件加载到数据框中

如何将字符串中带有双引号的json文件加载到spark scala中的数据框中

如何将数据加载到组合框中?

使用按钮单击和文本框加载 JSON 数据

将大型 csv 加载到数据框中,同时保持列结构