如何将字符串形式的字典列安全解析并展开为多列

本文介绍如何在 python 中安全地将 dataframe 中存储为字符串的字典(如 `"{827056812014862: [0.05, 0.0608, 0.476464, 0.53535]}"`)解析为结构化表格,提取键为 `id`、列表元素依次映射为 `t1`, `t2`, `t3`, `t4` 等独立列。

在实际数据处理中,常遇到将嵌套结构以字符串形式存储于单列的情况(例如日志导出、API 响应或低规范数据库导出)。直接使用 eval() 解析存在严重安全风险,推荐使用 ast.literal_eval() —— 它仅支持安全的字面量(如 dict、list、float、int、str),可有效防止代码注入。

以下是一个完整、健壮的解决方案:

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 records = [] for s in df["column_A"]: try: d = literal_eval(s) # 安全转换字符串为 dict for key, values in d.items(): if isinstance(values, (list, tuple)) and len(values) == 4: records.append({ "id": key, "t1": values[0], "t2": values[1], "t3": values[2], "t4": values[3] }) else: raise ValueError(f"Unexpected value format: {values}") except (ValueError, SyntaxError) as e: print(f"Warning: Skipping invalid string '{s}' — {e}") continue result = pd.DataFrame(records) 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():它可执行任意 Python 表达式,存在严重安全隐患;literal_eval() 是唯一推荐替代方案。
  • ⚠️ 添加异常处理:真实数据中可能存在格式错误、空值或长度不一致的列表,务必用 try/except 包裹解析逻辑。
  • ? 扩展性建议:若列表长度不固定,可用 **{f"t{i}": v for i, v in enumerate(values, 1)} 动态生成列名(如答案中所示),再通过 pd.json_normalize() 或 pd.concat() 统一列结构。
  • ? 性能优化(大数据量):对超大规模数据,可改用 apply + pd.Series 向量化展开(需确保每行仅含一个 key-value 对),但需注意内存开销。

该方法兼顾安全性、可读性与工程鲁棒性,适用于 ETL 流程、数据清洗及 Pandas 标准化预处理场景。