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

如何更优雅高效地实现字符串JSON列的DataFrame转换?

优化JSON字符串列解析为结构化DataFrame的方案

问题背景

原始DataFrame的info列存储JSON格式字符串:

info
{"any_name":{"value":["5"], "ref":"any text"}, "another_name":{"value":["2"], "ref":"any text"}
  {"any_name":{"value":["1"], "ref":"any text"}, "another_name":{"value":["12"], "ref":"any text"}

该列数据类型为str,目标是转换为以下结构化DataFrame:

any_name  another_name
    5          2
    1          12

原实现方案如下(可运行但效率和安全性不足):

A=list(df['answers'])

J=[]
for i in range(0,len(A)):
    D=eval(A[i])
    foo = {k: v['value'] for k, v in D.items() if k in list_to_filter_columns}
    J.append(foo)
out=pd.DataFrame(J)

# 转换数值类型
outt = outt.apply(lambda x: x.str[0])
outt = outt.apply(pd.to_numeric)
outt.head(2)

更高效优雅的实现方案

核心优化点

  • 替换eval为json.loads:消除安全风险,提升解析效率
  • 用pd.json_normalize替代手动循环:利用pandas向量式操作简化代码,提升性能

完整优化代码

import json
import pandas as pd

# 链式调用完成解析、过滤、格式转换
result = df['info']\
           .apply(json.loads)\
           .pipe(pd.json_normalize)\
           .filter(regex=r'^({})\.value'.format('|'.join(list_to_filter_columns)))\
           .rename(columns=lambda col: col.split('.')[0])\
           .applymap(lambda x: pd.to_numeric(x[0]))

result.head()

代码分步说明

  1. 解析JSON字符串:df['info'].apply(json.loads)将每个JSON字符串转为Python字典,相比eval,json.loads专门处理JSON格式,无代码执行风险,速度更快。
  2. 展开嵌套结构:.pipe(pd.json_normalize)把嵌套的字典结构展开为扁平DataFrame,列名自动生成为key.value、key.ref格式。
  3. 过滤目标字段:.filter(regex=r'^({})\.value'.format('|'.join(list_to_filter_columns)))通过正则匹配,只保留目标列的value字段,精准筛选需要的数据。
  4. 重命名列名:.rename(columns=lambda col: col.split('.')[0])将列名从any_name.value简化为any_name,符合目标格式。
  5. 转换数值类型:.applymap(lambda x: pd.to_numeric(x[0]))批量取出每个value列表的第一个元素,并转为数值型,applymap比逐列apply的执行效率更高。

额外优化建议

如果你的list_to_filter_columns是固定的(比如["any_name", "another_name"]),可以直接写死字段名,避免字符串拼接的开销:

# 固定列时的简化写法
result = df['info']\
           .apply(json.loads)\
           .pipe(pd.json_normalize)\
           .filter(['any_name.value', 'another_name.value'])\
           .rename(columns=lambda col: col.split('.')[0])\
           .applymap(lambda x: pd.to_numeric(x[0]))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:30:26