【问题标题】:Reading huge number of json files in Python?在 Python 中读取大量 json 文件?
【发布时间】:2017-05-29 01:26:42
【问题描述】:

这不是关于读取大型 JSON 文件,而是关于以最有效的方式读取大量 JSON 文件。

问题

我正在使用来自Million song dataset 的last.fm 数据集。 数据以一组 JSON 编码的文本文件的形式提供,其中的键是:track_id、艺术家、标题、时间戳、相似和标签。

目前,在经历了几个选项后,我正在通过以下方式将它们读入 pandas,因为这是最快的,如 here 所示:

import os
import pandas as pd
try:
    import ujson as json
except ImportError:
    try:
        import simplejson as json
    except ImportError:
        import json


# Path to the dataset
path = "../lastfm_train/"

# Getting list of all json files in dataset
all_files = [os.path.join(root,file) for root, dirs, files in os.walk(path) for file in files if file.endswith('.json')] 

data_list=[json.load(open(file)) for file in all_files]
df = pd.DataFrame(data_list, columns=['similars', 'track_id'])
df.set_index('track_id', inplace=True)

当前方法读取子集(不到一秒内读取完整数据集的 1%)。然而,阅读完整的火车集太慢了,而且需要很长时间(我也等了几个小时)才能阅读,并且已经成为进一步任务的瓶颈,例如 question here 中所示。

我还使用ujson 来提高解析json 文件的速度,这可以从this question here 中明显看出

更新 1 使用生成器推导而不是列表推导。

data_list=(json.load(open(file)) for file in all_files)

【问题讨论】:

  • 好像你没有足够的RAM,它开始使用SWAP,最简单的解决方案是获得更多的RAM。
  • @FranciscoCouzo 也许是最简单的......但绝对不是最便宜的! :D
  • 我已经有 16Gigs 了,我认为这对于读取这样的普通数据集来说绝对足够了。有没有更好的方法来读取这么多的 json 文件?
  • 一个接一个地读取所有 JSON,然后将您想要的列写入 CSV 将是微不足道的,几乎不占用 RAM,并简化格式,以便 Pandas、Numpy 或其他任何可以读取它以一种可能更有效的方式聚集在一起。
  • 来自labrosa.ee.columbia.edu/millionsong/lastfm "因为遍历 JSON 文件效率低下,而且大多数人只会处理相似性或标签,我们提供了两个 SQLite 数据库 数据。"。下载然后pd.read_sql('SELECT similars, track_id FROM ...', ...)。

标签: python json pandas


【解决方案1】:

如果您需要多次读取和写入数据集,您可以尝试将.json 文件转换为更快的格式。例如,在 pandas 0.20+ 中,您可以尝试使用 .feather 格式。

【讨论】:

    【解决方案2】:

    我会在文件和 yield 你想要的两列上构建一个迭代器。

    然后您可以使用该迭代器实例化 DataFrame。

    import os
    import json
    import pandas as pd
    
    # Path to the dataset
    path = "../lastfm_train/"
    
    def data_iterator(path):
        for root, dirs, files in os.walk(path):
            for f in files:
                if f.endswith('.json'):
                    fp = os.path.join(root,f)
                    with open(fp) as o:
                        data = json.load(o)
                    yield {"similars" : data["similars"], "track_id": data["track_id"]}
    
    
    df = pd.DataFrame(data_iterator(path))
    df.set_index('track_id', inplace=True)
    

    这样你只检查你的文件列表一次,你不会在传递给DataFrame之前和之后复制数据

    【讨论】:

    • 请查看更新,已经使用生成器理解。
    • 使用我发布的代码(带有原生包json),我在104 seconds中加载了完整的火车集数据集
    • 我的代码和您的代码在 1.04 秒内加载子集(1%),因此,预计完整加载大约 100 秒。但是,在我的机器上,您的代码需要 406 秒,而我的代码需要 473 秒。我正在使用具有 16GB RAM 的 Macbook Pro 2015 版本。您正在使用什么野兽来完美地扩展到完整的数据集?
    • :-) 我在这样的专用服务器上工作:ovh.co.uk/dedicated_servers/…
    • 认真的吗?我希望你在开玩笑。
    猜你喜欢
    • 2014-05-19
    • 2018-05-08
    • 2021-10-21
    • 1970-01-01
    • 2017-12-24
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多