【问题标题】:Pandas Dataframe from stacked json files - Speed issue来自堆叠的 json 文件的 Pandas Dataframe - 速度问题
【发布时间】:2020-10-06 11:30:16
【问题描述】:

我想导入一个 json 文件(尽管它看起来更像是一个普通的 txt 文件),其中每一行都是一个小的(四个数据对)json 文件。 每个 json 文件都应该是 pandas Dataframe 中的一行,有四列。

例子:

# Inside "data.json"

{"time": "2020-07-01:14:27:16.0000", "id": "m38dk117", "position": "66277", "active_current": "17.1"}
{"time": "2020-07-01:14:27:16.0000", "id": "m38dk118", "position": "3277", "active_current": "0.0"}
...
{"time": "2020-07-30:14:27:16.0000", "id": "m38dk006", "position": "73117", "active_current": "0.0"}

data.json 大约 30MB 大,包含大约 250.000 行 - 每天

data.json 大约 900MB 大,包含大约 750 万行 - 每个月

以下代码 sn-p 确实可以完成这项工作,但速度太慢了。 也欢迎熊猫的替代选择,我不仅限于熊猫。但缺乏处理大量日志数据的经验。

命题:

import pandas as pd
import json

df = pd.DataFrame()
with open('data.json', 'r') as stacked_json_file:
    row_idx = -1

    for json_file in stacked_json_file:
        row_idx += 1
        
        df = df.append(pd.DataFrame(json.loads(json_file), index = [row_idx]))

这可能是因为 pd.DataFrame.append 没有就地追加而变慢吗?

【问题讨论】:

  • 尝试通过read_json df = pd.read_json('data.json') 直接将 json 读取到 pandas
  • 附带说明:您必须使用的数据格式非常低效。一个(压缩的)csv 文件可以节省大量的空间和时间来导入。我知道它通常不在我们手中,但我会考虑要求数据源更改格式。

标签: python json pandas dataframe


【解决方案1】:

这应该可以工作

pd.read_json('data.json', lines=True)

输出:

                       time        id  position  active_current
0  2020-07-01:14:27:16.0000  m38dk117     66277            17.1
1  2020-07-01:14:27:16.0000  m38dk118      3277             0.0
2  2020-07-30:14:27:16.0000  m38dk006     73117             0.0

如果这不起作用:

假设您的数据不是有效的 json,而是一个文本文件,每行都有一个 json 对象。您可以先创建一个字典列表以避免附加到数据框

with open('data.json', 'r') as f:
  dictlist = [json.loads(x) for x in f]
pd.DataFrame(dictlist)

输出:

                       time        id position active_current
0  2020-07-01:14:27:16.0000  m38dk117    66277           17.1
1  2020-07-01:14:27:16.0000  m38dk118     3277            0.0
2  2020-07-30:14:27:16.0000  m38dk006    73117            0.0

微基准

比较迭代追加,创建字典列表和pd.read_json

结果

用于基准测试的代码

import pandas as pd
import json
import io

def makedata(n):
  t = '''{"time": "2020-07-01:14:27:16.0000", "id": "m38dk117", "position": "66277", "active_current": "17.1"}
{"time": "2020-07-01:14:27:16.0000", "id": "m38dk118", "position": "3277", "active_current": "0.0"}
{"time": "2020-07-30:14:27:16.0000", "id": "m38dk006", "position": "73117", "active_current": "0.0"}
''' * n
  return t

def pdjson(file):
  return pd.read_json(io.StringIO(file), lines=True)

def dictlist(file):
  with io.StringIO(file) as f:
    l = [json.loads(x) for x in f]
  return pd.DataFrame(l)

def appenddf(file):
  df = pd.DataFrame()
  with io.StringIO(file) as stacked_json_file:
      row_idx = -1

      for json_file in stacked_json_file:
          row_idx += 1
          
          df = df.append(pd.DataFrame(json.loads(json_file), index = [row_idx]))
  return df

import perfplot
perfplot.show(
    setup = makedata,
    kernels = [appenddf, dictlist, pdjson],
    n_range= [2**k for k in range(5,16)],
    equality_check=None,
    xlabel='len(df)'
);

【讨论】:

  • 谢谢。完美运行。作为旁注:在 dictlist-approach 中:用 () 替换 [] 来创建生成器,效率更高还是可以忽略不计?如果是这样,如何检查?
  • 我将列表和生成器与测试数据的小文件 (~200 MB) 进行了比较:运行时差异可以忽略不计。因此,对于大文件,如果内存使用受到关注,您使用生成器的想法似乎是一个不错的选择。
猜你喜欢
  • 2012-08-28
  • 2022-01-08
  • 2018-04-12
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-03
  • 2016-11-02
相关资源
最近更新 更多