【问题标题】:Reading a specific number of randomly-chosen json entries读取特定数量的随机选择的 json 条目
【发布时间】:2020-07-08 18:45:01
【问题描述】:

Python3/Jupyter Notebook 问题。我有一个大的 json(> 300 万个条目)。我正在尝试将 50,000 个随机条目读入列表,并要求这些随机条目具有特定值的“country_code”参数。现在我正在阅读 300 万个条目中的每一个,缩小到具有正确国家代码的条目,然后从该子列表中获取 50,000 个随机元素。我只想阅读 50,000 条带有正确国家代码的随机行,而不必先阅读全部 300 万行。当前方法耗时太长。

我当前的代码:

def filter_json_by_country(filename, country):
    file = Path(filename)
    data = list()
    
    with file.open('r') as f:
        for line in f:
            data.append(json.loads(line))

    loc_filtered_data = []
    for i in range(len(data)):
        if len(data[i]['user_location']) != 0 and data[i]['user_location']['country_code'] == country:
            loc_filtered_data.append(data[i])

    ids = [loc_filtered_data[i]['tweet_id'] for i in range(len(loc_filtered_data))]
    ids = random.sample(ids, 50000) 
    return ids

已编辑——json 示例:

{
     "tweet_id":"1231698465102663680",
     "created_at":"Sun Feb 23 21:52:52 +0000 2020",
     "user_id":"433036746",
     "geo_source":"tweet_text",
     "user_location":{},
     "geo":{},
     "place":{},
     "tweet_locations":
        [
            {
                "country_code":"us",
                "state":"Illinois"},
            {
                "country_code":"fr",
                "state":"Auvergne-Rh\u00f4ne-Alpes",
                "county":"Die"},
            {
                "country_code":"it",
                "state":"Piemont",
                "county":"TO",
                "city":"Porte"},
            {
                "country_code":"fr",
                "state":"Occitania",
                "county":"Castres",
                "city":"Lacaze"},
            {
                "country_code":"br",
                "state":"Sergipe",
                "county":"Microrregi\u00e3o do Baixo S\u00e3o Francisco Sergipano",
                "city":"Propri\u00e1"}
        ]
}

【问题讨论】:

  • 请不要标记您的 IDE 或代码编辑器,除非您的问题与编辑器本身特别相关。
  • 如果您将 JSON 数据加载到 Pandas 数据框中,这可能会更有效地完成。
  • 您能提供一个示例 json 吗?
  • @MZ 是的,刚刚更新
  • @MZ 他们确实提供了帮助,谢谢!! (是的,我美化了 json。)

标签: python json python-3.x dictionary


【解决方案1】:

线性减少时间的快速修复:

def filter_json_by_country(filename, country):
    file = Path(filename)
    loc_filtered_data = []

    with file.open('r') as f:
        for line in f:
            data = json.loads(line)
            if len(data['user_location']) != 0 and data['user_location']['country_code'] == country:
                loc_filtered_data.append(data)
        

    ids = [loc_filtered_data[i]['tweet_id'] for i in range(len(loc_filtered_data))]
    ids = random.sample(ids, 50000) 
    return ids

当且仅当数据已经满足时才会添加数据,因此您可以减少需要遍历所有 JSON 数据的次数。

这是一个将随机化合并到同一个循环中的方法:

def filter_json_by_country(filename, country):    
    loc_filtered_data = []
    length = -1
    with open(filename, 'r') as f:
        for length, l in enumerate(f):
            pass
        
        # Do randomizing before loading json
        shuffled = list(range(length + 1))
        random.shuffle(shuffled)

        for i in shuffled:
            if len(loc_filtered_data) >= 50_000:
                break
            f.seek(i, 0)
            data = json.loads(f.readline())
            
            # only append data if it satisfy the requirements
            if len(data['user_location']) != 0 and data['user_location']['country_code'] == country:
                loc_filtered_data.append(data[i])

    ids = [loc_filtered_data[i]['tweet_id'] for i in range(len(loc_filtered_data))]
    
    return ids

seeking 的速度取决于机器。如果您能够比这更快地确定文件中的行数,它会更快。但这里的想法是,您只需要准确地遍历 50,000 个有效条目(如果有无效条目则更多)。

【讨论】:

    【解决方案2】:

    为什么要使用行分隔的 json?

    如果你给你的函数计时,加载 json 可能需要 99% 的时间。您是否考虑过使用某种允许任意访问的表,而不是强迫您事后进行过滤?

    如果您必须保持 json 格式,请尝试加载它,将其腌制,然后加载腌制文件,我已经看到像这样的智能缓存有合理的性能。

    作为另一种选择,尝试在使用 json 解析之前查找国家/地区代码(子字符串搜索,甚至是“grep”)。

    【讨论】:

      猜你喜欢
      • 2020-12-01
      • 1970-01-01
      • 2014-04-28
      • 2012-09-06
      • 2022-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-02
      相关资源
      最近更新 更多