将字符串格式的字典安全解析并展开为多列结构化数据

本文介绍如何使用 ast.literal_eval 安全解析 dataframe 中形如 {key: [v1, v2, v3, v4]} 的

字符串列,并将其高效拆分为独立的 id 与数值列(如 id、t1–t4),避免 eval() 的安全风险,适用于日志、api 响应等场景下的非标准 json 数据清洗。

在实际数据处理中,我们常遇到存储为字符串的类字典结构(例如数据库导出或 API 返回的非标准 JSON 字段),如 "{827056812014862: [0.05, 0.0608, 0.476464, 0.53535]}"。这类数据无法直接用 pd.json_normalize() 解析,且使用 eval() 存在严重安全风险。推荐方案是借助 Python 标准库中的 ast.literal_eval ——它仅允许解析基础字面量(数字、字符串、元组、列表、字典、布尔值和 None),可安全反序列化可信但非标准的字符串字典。

以下为完整实现步骤:

第一步:导入必要模块

import pandas as pd
from ast import literal_eval

第二步:构造示例数据

df = pd.DataFrame({
    "column_A": [
        "{827056812014862 : [0.05, 0.0608, 0.476464, 0.53535]}",
        "{263746262748835 : [0.08, 0.0333, 0.8263, 0.9463]}",
        "{63673738736362 : [0.05, 0.0926, 0.8694, 0.9903]}",
        "{73737681201484 : [0.08, 0.0425, 0.1948, 0.3958]}"
    ]
})

第三步:解析并展开为结构化 DataFrame

out = []
for d in df["column_A"].apply(literal_eval):
    for key, values in d.items():
        # 确保 values 是长度为 4 的列表(可根据实际调整)
        if not isinstance(values, (list, tuple)) or len(values) != 4:
            raise ValueError(f"Unexpected value format for key {key}: {values}")
        out.append({
            "id": key,
            "t1": values[0],
            "t2": values[1],
            "t3": values[2],
            "t4": values[3]
        })

result = pd.DataFrame(out)
print(result)

输出结果严格匹配预期:

                id    t1      t2        t3       t4
0  827056812014862  0.05  0.0608  0.476464  0.53535
1  263746262748835  0.08  0.0333  0.826300  0.94630
2   63673738736362  0.05  0.0926  0.869400  0.99030
3   73737681201484  0.08  0.0425  0.194800  0.39580

? 关键注意事项:

  • 永远避免 eval():literal_eval 是唯一安全替代方案,防止任意代码执行;
  • ⚠️ 健壮性增强建议:生产环境应添加异常捕获(如 try/except)和空值/格式校验;
  • ? 灵活扩展:若列表长度不固定,可用 **{f"t{i}": v for i, v in enumerate(values, 1)} 动态生成列名;
  • ? 性能提示:对超大数据集,可改用 pd.json_normalize() 配合预处理(如正则提取 + json.loads),或向量化 apply + pd.Series(需确保结构统一)。

该方法简洁、安全、可维护,是处理“伪字典字符串”列的标准实践。