You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何进一步优化JSON响应片段转pd.DataFrame的加载效率?

问题描述

我有一个包含大量大型JSON响应的pandas Series,之前尝试仅加载JSON对象的部分内容并转换为pd.DataFrame时,遇到内存占用过高、处理速度缓慢的问题。我写了下面的代码,已经规避了多数性能问题,但想知道有没有更高效的实现方式,寻求代码优化建议。

示例数据

{0: '{"city":"Campinas","bot-origin":null,"campaign-source":null,"lastState":"productAvailabilityCpfRequest","main-installation-date":"22/09/2021","userid":"c46528a7-988d-465e-9f12-25426a8b1808@tunnel.msging.net","full-name":"Claudenice lôbo da silva","alternative-installation-date":"23/09/2021","chosen-product":"Internet","bank":null,"postalcode":"13056015","due-date":"20","cpf":"30979696836","origin-link":null,"payment":"boleto","state":"SP","api-orders-hash-id":null,"email":"Silvaclaudenice71@gmail.com","plan-name":null,"userphone":"19 98715-0491","plan-offer":null,"completed-address":"13056015 - AV FERNANDO PAOLIERI, 182 - JARDIM PLANALTO DE VIRACOPOS, Campinas - SP","type-of-person":"CPF","type-of-product":"Residencial","main-installation-period-day":"manhã","plan-value":null,"alternative-installation-period-day":"manhã"}', 1: '{"city":"Campinas","bot-origin":null,"campaign-source":null,"lastState":"productAvailabilityStart","main-installation-date":"22/09/2021","userid":"c46528a7-988d-465e-9f12-25426a8b1808@tunnel.msging.net","full-name":"Claudenice lôbo da silva","alternative-installation-date":"23/09/2021","chosen-product":"Internet","bank":null,"postalcode":"13056015","due-date":"20","cpf":"30979696836","origin-link":null,"payment":"boleto","state":"SP","api-orders-hash-id":null,"email":"Silvaclaudenice71@gmail.com","plan-name":null,"userphone":"19 98715-0491","plan-offer":null,"completed-address":"13056015 - AV FERNANDO PAOLIERI, 182 - JARDIM PLANALTO DE VIRACOPOS, Campinas - SP","type-of-person":"CPF","type-of-product":"Residencial","main-installation-period-day":"manhã","plan-value":null,"alternative-installation-period-day":"manhã"}', 2: '{"city":"Campinas","bot-origin":null,"campaign-source":null,"lastState":"cpfValidationTrue","main-installation-date":"22/09/2021","userid":"c46528a7-988d-465e-9f12-25426a8b1808@tunnel.msging.net","full-name":"Claudenice lôbo da silva","alternative-installation-date":"23/09/2021","chosen-product":"Internet","bank":null,"postalcode":"13056015","due-date":"20","cpf":"30979696836","origin-link":null,"payment":"boleto","state":"SP","api-orders-hash-id":null,"email":"Silvaclaudenice71@gmail.com","plan-name":null,"userphone":"19 98715-0491","plan-offer":null,"completed-address":"13056015 - AV FERNANDO PAOLIERI, 182 - JARDIM PLANALTO DE VIRACOPOS, Campinas - SP","type-of-person":"CPF","type-of-product":"Residencial","main-installation-period-day":"manhã","plan-value":null,"alternative-installation-period-day":"manhã"}', 3: '{"city":"Campinas","bot-origin":null,"campaign-source":null,"lastState":"productAvailabilityCpfRequest","main-installation-date":"22/09/2021","userid":"c46528a7-988d-465e-9f12-25426a8b1808@tunnel.msging.net","full-name":"Claudenice lôbo da silva","alternative-installation-date":"23/09/2021","chosen-product":"Internet","bank":null,"postalcode":"13056015","due-date":"20","cpf":"30979696836","origin-link":null,"payment":"boleto","state":"SP","api-orders-hash-id":null,"email":"Silvaclaudenice71@gmail.com","plan-name":null,"userphone":"19 98715-0491","plan-offer":null,"completed-address":"13056015 - AV FERNANDO PAOLIERI, 182 - JARDIM PLANALTO DE VIRACOPOS, Campinas - SP","type-of-person":"CPF","type-of-product":"Residencial","main-installation-period-day":"manhã","plan-value":null,"alternative-installation-period-day":"manhã"}', 4: '{"city":"Campinas","bot-origin":null,"campaign-source":null,"lastState":"productAvailabilityStart","main-installation-date":"22/09/2021","userid":"c46528a7-988d-465e-9f12-25426a8b1808@tunnel.msging.net","full-name":"Claudenice lôbo da silva","alternative-installation-date":"23/09/2021","chosen-product":"Internet","bank":null,"postalcode":"13056015","due-date":"20","cpf":"30979696836","origin-link":null,"payment":"boleto","state":"SP","api-orders-hash-id":null,"email":"Silvaclaudenice71@gmail.com","plan-name":null,"userphone":"19 98715-0491","plan-offer":null,"completed-address":"13056015 - AV FERNANDO PAOLIERI, 182 - JARDIM PLANALTO DE VIRACOPOS, Campinas - SP","type-of-person":"CPF","type-of-product":"Residencial","main-installation-period-day":"manhã","plan-value":null,"alternative-installation-period-day":"manhã"}'}

现有代码

import orjson
def dataset_extras(extras, *args): # extras是传入的Series,args是需要提取的键列表
    l = [] 
    for i in extras:
        l.append({arg : orjson.loads(i).get(arg) for arg in args})
    return pd.DataFrame.from_records(l)

# 调用示例
dataset_extras(df.Extras,'city','campaign-source','api-orders-hash-id')

优化建议

1. 避免重复解析JSON

当前代码每次循环都重复解析同一段JSON字符串,可先解析一次再提取所有需要的键,减少解析开销:

def dataset_extras(extras, *args):
    records = []
    for json_str in extras:
        data = orjson.loads(json_str)
        records.append({arg: data.get(arg) for arg in args})
    return pd.DataFrame.from_records(records)

2. 用pandas矢量化操作替代Python循环

利用pd.Series.apply结合自定义函数,借助pandas内部优化减少Python层面的循环开销:

def extract_keys(json_str, keys):
    data = orjson.loads(json_str)
    return {k: data.get(k) for k in keys}

def dataset_extras(extras, *args):
    extracted = extras.apply(lambda x: extract_keys(x, args))
    return pd.DataFrame(extracted.tolist())

3. 分块处理超大Series

如果Series数据量极大导致内存紧张,可分块处理后拼接结果,降低单批次内存占用:

def dataset_extras(extras, *args, chunk_size=10000):
    chunks = []
    for start in range(0, len(extras), chunk_size):
        chunk = extras.iloc[start:start+chunk_size]
        records = []
        for json_str in chunk:
            data = orjson.loads(json_str)
            records.append({arg: data.get(arg) for arg in args})
        chunks.append(pd.DataFrame.from_records(records))
    return pd.concat(chunks, ignore_index=True)

4. 提前指定数据类型减少内存

创建DataFrame时,根据已知字段类型指定dtype,避免pandas自动推断带来的内存浪费:

def dataset_extras(extras, *args):
    records = []
    for json_str in extras:
        data = orjson.loads(json_str)
        records.append({arg: data.get(arg) for arg in args})
    # 根据实际字段类型调整映射
    dtype_map = {
        'city': 'string',
        'campaign-source': 'string',
        'api-orders-hash-id': 'string'
    }
    used_dtypes = {k: v for k, v in dtype_map.items() if k in args}
    return pd.DataFrame.from_records(records, dtype=used_dtypes)

5. 用orjson选项加速解析

orjson支持多种解析选项,若无需处理日期等特殊类型,可关闭相关校验进一步提升速度:

data = orjson.loads(json_str, option=orjson.OPT_DISABLE_STRICT_INTEGER_CHECK)

内容的提问来源于stack exchange,提问作者INGl0R1AM0R1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:36:32