【问题标题】:Reading multiple JSON records into a Pandas dataframe将多个 JSON 记录读入 Pandas 数据帧
【发布时间】:2013-11-30 23:48:21
【问题描述】:

我想知道是否有一种内存有效的方法可以将多记录 JSON 文件(每行是一个 JSON 字典)读入 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)

【问题讨论】:

  • 使用 pd.read_json 的 chunksize 属性获取数据帧列表,并使用 map 或循环遍历数据帧

标签: python json pandas


【解决方案1】:

注意:read_json(从 0.19.0 开始)现在支持行分隔的 json:

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

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

pd.read_json(json_file, lines=True)

这将取决于更快的 DataFrame 的大小,但另一种选择是使用 str.join 将多行“JSON”(注意:它不是有效的 json)粉碎成有效的 json 并使用 read_json:

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

对于这个小例子,这会更慢,如果在 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

注意:那个时候连接速度出奇的快。

【讨论】:

  • 不包括读取字符串的时间(两种解决方案都使用),我想知道这里是否有技巧......
  • 我必须像data = pd.read_json('/path/to/file.json', lines=True)一样添加lines=True
  • 如果 json 中发生错误,它似乎不适用于大型 json 文件。
  • @devssh 请在 GitHub 上发布问题
  • 所以,在 Github github.com/pandas-dev/pandas/issues/18152 上有一个已解决的问题,我验证了大文件中的多个 json 不是无效的,并成功地分块加载了它们。 dfs = pd.read_json('file', lines=True, chunksize=x)for df in dfs: df.head()
【解决方案2】:

如果你想节省内存,那么一次读取一行文件会更节省内存:

with open('test.json') as f:
    data = pd.DataFrame(json.loads(line) for line in f)

另外,如果你import simplejson as jsonsimplejson 包含的编译 C 扩展比纯 Python json 模块快得多。

【讨论】:

  • 其实我认为 DataFrame 构造函数做的第一件事就是在这样的生成器上调用列表,所以内存和时间都是一样的。 simplejson 的性能介于 pandas 的 read_json 和 json 之间。
  • 啊,太糟糕了;看来您对 DataFrame 构造函数是正确的。最新版本的 Python 包括内置 json 的已编译 C 扩展。幸运的是,从 Pandas 0.19 开始,您可以使用 read_json(lines=True)
  • @AndyHayden:这仍然会比 OP 的 l=[ json.loads(l) for l in test.splitlines()] 节省内存,它需要在内存中同时拥有:1.原始完整文件数据,2.文件数据拆分为行(在所有行解析后删除),以及 3. 解析的 JSON 对象。懒惰地读取并逐行加载意味着您​​只有上面的#3,加上内存中的文件的一行(技术上是两行,但逻辑上是一行)。当然,所有已解析的对象都在内存中,但没有两个要引导的文件数据的额外副本。
  • @ShadowRanger 不,DataFrame 构造函数所做的第一件事是将list 应用于迭代器。完全等价。
  • @AndyHayden:如果被迭代的可迭代是等价的,那将是等价的,但 OP 的可迭代是 test.splitlines()(意思是 test 和结果行的 list 都保存在内存中,而list 已构建),而 Doctor J 的可迭代对象是 f(一个打开的文件对象),它会拉动每一行,并在每个 json.loads 之后立即替换它。 pd.DataFrame(json.loads(line) for line in f)pd.DataFrame([json.loads(line) for line in f]) 是等价的(前listDataFrame 化,后者直接生成list),但文件与str.split 不同。
【解决方案3】:

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

从 v0.19 开始,Pandas 原生支持此功能(请参阅 https://github.com/pandas-dev/pandas/pull/13351)。运行:

df=pd.read_json('test.json', lines=True)

++++++++老答案++++++++++

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

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

在 ipython notebook 中,您可以直接从单元界面运行 shell 命令

!cat test.json | jq -c --slurp . > valid_test.json
df=pd.read_json('valid_test.json')

【讨论】:

    【解决方案4】:

    从 Pandas 0.19 开始,read_json 原生支持 line-delimited JSON

    pd.read_json(jsonfile, lines=True)
    

    【讨论】:

      猜你喜欢
      • 2017-06-23
      • 2017-08-13
      • 1970-01-01
      • 2020-05-01
      • 2023-03-25
      • 1970-01-01
      • 2019-11-23
      • 1970-01-01
      相关资源
      最近更新 更多