相关文章推荐
苦闷的蚂蚁  ·  mybatisplus 索引注解 - CSDN文库·  15 小时前    · 
不敢表白的钱包  ·  node: ...·  11 小时前    · 
坚强的大象  ·  Preparing metadata ...·  58 分钟前    · 
有胆有识的鼠标垫  ·  (gdb) break ...·  1 月前    · 
欢快的冰棍  ·  可视化工具D3入门 - 知乎·  1 年前    · 
卖萌的煎鸡蛋  ·  Postgres SQL sort ...·  1 年前    · 
犯傻的手链  ·  linux ...·  1 年前    · 

在Python中优化json.load()以减少内存的使用和时间

1 人关注

我有10K个文件夹,每个文件夹有200个JSON格式文件的200条记录。 试图将所有的记录编入一个数据框架,然后最后编入CSV(欢迎其他格式的建议)。

这是我的工作方案,仅建立数据框架的过程就花了大约8.3小时。(未转换为CSV)

%%time
finalDf = pd.DataFrame()
rootdir ='/path/foldername'
all_files = Path(rootdir).rglob('*.json')
for filename in all_files:
    with open(filename, 'r+') as f:
        data = json.load(f)
        df = pd.json_normalize(data).drop(columns=[A]).rename(columns={'B': 'Date'})
        finalDf = finalDf.append(df, ignore_index=True)

有什么建议可以优化这一点,使时间减少。

5 个评论
我发现了类似的帖子。试试这个怎么样? stackoverflow.com/questions/27407430/...
Abhi
是的,将尝试超JSON的用法。但不是很乐观。
你使用的是什么平台?这需要在Windows上运行吗?
目标是仅仅写CSV,还是要先处理完整的DF?
还有其他更快的序列化方式,如feather、parquet、hdf文件系统。根据你想长期处理数据的需要,像mongdb或者甚至好的sql这样的nosql解决方案也是不错的选择。一旦你导入了这些json,你就有了丰富的查询能力,如果随着时间的推移,json越来越多,只要继续导入就可以了。
python
json
dataframe
optimization
Abhi
Abhi
发布于 2020-07-15
2 个回答
Jérôme Richard
Jérôme Richard
发布于 2020-07-15
已采纳
0 人赞同

一个重要的问题来自于 O(n^2) 中执行数据帧追加。 .事实上,对于每一个新处理的json文件, finalDf 都是完全复制的!

这里是一个在 O(n) 时间内运行的修改版。

%%time
finalDf = pd.DataFrame()
rootdir ='/path/foldername'
all_files = Path(rootdir).rglob('*.json')
allDf = []
for filename in all_files:
    with open(filename, 'r+') as f:
        data = json.load(f)
        df = pd.json_normalize(data).drop(columns=[A]).rename(columns={'B': 'Date'})
        allDf.append(df)
finalDf = pd.concat(allDf, ignore_index=True)

如果这还不够,json解析和pandas后处理可以通过以下方式并行执行multiprocessing module.

Abhi
这当然有帮助。你能否详细说明一下 json解析和pandas后处理可以使用多处理模块并行执行。 .有什么实现方法/代码吗?
tdelaney
tdelaney
发布于 2020-07-15
0 人赞同

如果目标只是写CSV,你可以使用多进程来并行化读取/反序列化/序列化的步骤,并用锁来控制文件的写入。对于CSV,你不必在内存中保留整个文件,只需在生成时追加每个DF。如果你使用的是硬盘而不是ssd,如果CSV在不同的驱动器上(不仅仅是分区),你也可能得到提升。

import multiprocessing as mp
import json
import pandas as pd
from pathlib import Path
import os
def update_csv(args):
    lock, infile, outfile = args
    with open(infile) as f:
        data = json.load(f)
    df = pd.json_normalize(data).drop(columns=[A]).rename(columns={'B': 'Date'})
    with lock:
        with open(outfile, mode="a", newline="") as f:
            df.to_csv(f)
if __name__ == "__main__":
    rootdir ='/path/foldername'
    outfile = 'myoutput.csv'
    if os.path.exists(outfile):
        os.remove(outfile)
    all_files = [str(p) for p in Path(rootdir).rglob('*.json')]
    mgr = mp.Manager()
    lock = mgr.Lock()
    # pool sizing is a bit of a guess....