pandas - 将多个JSON记录读入数据帧

sea*_*507 43 python json pandas

我想知道是否有一种以内存有效的方式将多记录JSON文件(每行是JSON dict)读入pandas数据帧.下面是一个带有工作解决方案的2行示例,我需要它可能用于非常大量的记录.示例用法是处理来自Hadoop Pig JSonStorage函数的输出.

import json
import pandas as pd

test='''{"a":1,"b":2}
{"a":3,"b":4}'''
#df=pd.read_json(test,orient='records') doesn't work, expects []

l=[ json.loads(l) for l in test.splitlines()]
df=pd.DataFrame(l)
Run Code Online (Sandbox Code Playgroud)

And*_*den 51

注意:现在支持行分隔的json read_json(自0.19.0起):

In [31]: pd.read_json('{"a":1,"b":2}\n{"a":3,"b":4}', lines=True)
Out[31]:
   a  b
0  1  2
1  3  4
Run Code Online (Sandbox Code Playgroud)

或者使用文件/文件路径而不是json字符串:

pd.read_json(json_file, lines=True)
Run Code Online (Sandbox Code Playgroud)

这将取决于你的DataFrames的大小更快,但另一种选择是使用str.join粉碎你的多行"JSON"(注意:它是无效的json),进入有效的json并使用read_json:

In [11]: '[%s]' % ','.join(test.splitlines())
Out[11]: '[{"a":1,"b":2},{"a":3,"b":4}]'
Run Code Online (Sandbox Code Playgroud)

对于这个微小的例子,这个速度较慢,如果大约100,那么如果它更大的话就会有相似的,显着的增益......

In [21]: %timeit pd.read_json('[%s]' % ','.join(test.splitlines()))
1000 loops, best of 3: 977 µs per loop

In [22]: %timeit l=[ json.loads(l) for l in test.splitlines()]; df = pd.DataFrame(l)
1000 loops, best of 3: 282 µs per loop

In [23]: test_100 = '\n'.join([test] * 100)

In [24]: %timeit pd.read_json('[%s]' % ','.join(test_100.splitlines()))
1000 loops, best of 3: 1.25 ms per loop

In [25]: %timeit l = [json.loads(l) for l in test_100.splitlines()]; df = pd.DataFrame(l)
1000 loops, best of 3: 1.25 ms per loop

In [26]: test_1000 = '\n'.join([test] * 1000)

In [27]: %timeit l = [json.loads(l) for l in test_1000.splitlines()]; df = pd.DataFrame(l)
100 loops, best of 3: 9.78 ms per loop

In [28]: %timeit pd.read_json('[%s]' % ','.join(test_1000.splitlines()))
100 loops, best of 3: 3.36 ms per loop
Run Code Online (Sandbox Code Playgroud)

注意:当时加入的速度非常快.


Doc*_*r J 27

如果您正在尝试节省内存,那么一次读取一行文件将更加节省内存:

with open('test.json') as f:
    data = pd.DataFrame(json.loads(line) for line in f)
Run Code Online (Sandbox Code Playgroud)

此外,如果您import simplejson as json,包含的已编译C扩展simplejson比纯Python json模块快得多.

  • 实际上我认为DataFrame构造函数所做的第一件事就是在这样的生成器上调用list,所以内存和时序都是一样的.simplejson的性能介于pandas的read_json和json之间. (2认同)

Doc*_*r J 14

从Pandas 0.19开始,read_json行分隔的JSON有本机支持:

pd.read_json(jsonfile, lines=True)
Run Code Online (Sandbox Code Playgroud)


Bob*_*ley 5

++++++++更新++++++++++++++++

从 v0.19 开始,Pandas 本身就支持这一点(参见https://github.com/pandas-dev/pandas/pull/13351)。赶紧跑:

df=pd.read_json('test.json', lines=True)
Run Code Online (Sandbox Code Playgroud)

++++++++旧答案++++++++++

现有的答案很好,但对于一些变化,这是实现目标的另一种方法,它需要在 python 之外进行简单的预处理步骤,以便pd.read_json()可以使用数据。

  • 安装 jq https://stedolan.github.io/jq/
  • 创建一个有效的 json 文件 cat test.json | jq -c --slurp . > valid_test.json
  • 创建数据框 df=pd.read_json('valid_test.json')

在 ipython notebook 中,你可以直接从 cell 界面运行 shell 命令

!cat test.json | jq -c --slurp . > valid_test.json
df=pd.read_json('valid_test.json')
Run Code Online (Sandbox Code Playgroud)