如何优化JSON转DataFrame的预处理代码以提升执行效率?
优化JSON转DataFrame代码的效率问题
用户提供的原始代码(用于将特定JSON数据转换为DataFrame)如下:
import json import pandas as pd import time with open('color.json', 'r') as f: json_color = json.load(f) df=pd.DataFrame(json_color) start = time.time() new_df=pd.DataFrame() index_list=[] for i in range(0,len(df)): for j,(key,value) in enumerate(df['result'][i]['RGB'].items()): key=key.split(',') df2 = pd.DataFrame(data=[[key[0],key[1],key[2],value]]) index_list.append(df['result'][i]['name'][:-4]+'_'+str(j)) new_df=pd.concat([new_df,df2]) new_df.index=index_list new_df.columns=[['R','G','B','percentile']] print(new_df) print(time.time()-start)
该代码可正常运行,但希望优化执行效率,以下是具体优化建议:
核心优化方向:避免循环中频繁拼接DataFrame
pd.concat在循环里反复调用会不断创建新对象,带来巨大的性能开销,尤其是数据量较大时。建议先收集所有数据到列表,最后一次性生成DataFrame。
优化方案1:预收集数据列表,一次性生成DataFrame
import json import pandas as pd import time with open('color.json', 'r') as f: json_color = json.load(f) start = time.time() data_rows = [] index_list = [] # 直接遍历json里的result列表,跳过不必要的中间DataFrame for item in json_color['result']: name_prefix = item['name'][:-4] for j, (rgb_key, percentile) in enumerate(item['RGB'].items()): r, g, b = rgb_key.split(',') data_rows.append([r, g, b, percentile]) index_list.append(f"{name_prefix}_{j}") # 一次性生成最终DataFrame new_df = pd.DataFrame(data_rows, index=index_list, columns=['R', 'G', 'B', 'percentile']) print(new_df) print(time.time() - start)
优化点说明:
- 去掉将原始JSON转为中间
df的冗余步骤,直接遍历json_color['result'] - 用列表
data_rows批量收集行数据,避免循环中多次concat的对象创建开销 - 用f-string格式化索引,比传统字符串拼接更高效简洁
优化方案2:利用pandas内置工具处理结构化JSON
如果原始JSON结构稳定,可借助json_normalize和向量化操作替代纯Python循环:
import json import pandas as pd import time with open('color.json', 'r') as f: json_color = json.load(f) start = time.time() # 展开嵌套的result结构 df_base = pd.json_normalize(json_color['result']) # 将RGB字典拆分为多行 df_rgb = df_base.explode('RGB').reset_index(drop=True) # 拆分RGB键值对 df_rgb[['R', 'G', 'B']] = df_rgb['RGB'].apply(lambda x: pd.Series(list(x.keys())[0].split(','))) df_rgb['percentile'] = df_rgb['RGB'].apply(lambda x: list(x.values())[0]) # 生成带序号的索引 df_rgb['index'] = df_rgb['name'].str[:-4] + '_' + df_rgb.groupby('name').cumcount().astype(str) # 整理最终结果 new_df = df_rgb.set_index('index')[['R', 'G', 'B', 'percentile']] print(new_df) print(time.time() - start)
优化点说明:
- 用
json_normalize和explode快速展开嵌套结构,比纯Python循环更高效 - 向量化
apply操作替代逐行遍历,利用pandas的底层优化提升速度 - 用
groupby.cumcount自动生成序号,避免手动维护计数器
其他细节优化
- 指定数据类型:生成DataFrame时明确指定列的
dtype,比如dtype={'R': int, 'G': int, 'B': int, 'percentile': float},减少后续类型推断的开销 - 流式读取大文件:如果JSON文件体积极大,可使用
ijson库流式读取,避免一次性加载全部数据到内存 - 移除冗余变量:原始代码中
df=pd.DataFrame(json_color)完全多余,直接遍历原始JSON数据即可
内容的提问来源于stack exchange,提问作者Chi0814
相关产品推荐
相关产品推荐

