下一篇:没有了
基于Pandas的动态JSON路径递归解析:可变深度嵌套字段自动展平方案
[ 2026/5/29 19:58:16 ]本文介绍如何从 deepdiff 生成的嵌套路径字符串(如 `root[''prod1''][''p_col''][''c_col'']`)中自动提取多级字段名,并动态构建对应数量的列,实现灵活、可扩展的变更分析表格。
在使用 deepdiff 比较嵌套 JSON 文档时,values_changed 字典的键是形如 root[''prod1''][''p_col''][''c_col2''][''c_col5''] 的路径字符串。若需将这些路径结构映射为结构化 DataFrame(例如区分 product、parent-field、field 等层级),硬编码切分逻辑(如多次 find/split)既脆弱又难以维护。理想方案是基于实际路径深度动态生成列,而非预设固定列数。
推荐采用正则 + str.extractall 的向量化方式,稳健提取所有方括号内的标识符:
复制AI写代码
import pandas as pd
import re
# 假设 values_changed 已从 DeepDiff 获取(字典格式)
values_changed = {
"root[''prod1''][''p_col''][''c_col'']": {"new_value": -2.866711109999983, "old_value": -2.75},
"root[''prod1''][''p_col23'']": {"new_value": 1, "old_value": 54},
"root[''prod1''][''p_col''][''c_col2''][''c_col5'']": {"new_value": 1.678, "old_value": 5.12}
}
# 步骤1:转为 DataFrame(行索引为原始路径)
df = pd.DataFrame.from_dict(values_changed, orient=''index'')
# 步骤2:用正则提取所有 [''xxx''] 中的字段名(忽略 ''root'')
# \[''(\w+)''\] 匹配单引号包围的字母数字字段;extractall 返回 MultiIndex Series
path_parts = df.index.str.extractall(r"\[''(\w+)''\]")[0]
# 步骤3:展开为宽表,每级对应一列;列名按语义映射(可扩展)
max_depth = path_parts.index.get_level_values(''match'').max() + 1
column_mapping = {0: ''product'', 1: ''parent-field''}
# 其余列统一命名为 ''field'',Pandas 自动处理重复列名(field, field, field...)
columns = [column_mapping.get(i, ''field'') for i in range(max_depth)]
# 步骤4:unstack 展开 + 重命名列 + 关联原数据
expanded = (path_parts.unstack(''match'')
.rename(columns=lambda i: columns[i] if i < len(columns) else ''field'')
.join(df.reset_index(drop=True)))
print(expanded)
输出结果将自动适配最长路径深度(本例为 4 级),生成如下结构:
product parent-field field field new_value old_value
prod1 p_col c_col NaN -2.866711 -2.75
prod1 p_col23 NaN NaN 1.000000 54.00
prod1 p_col c_col2 c_col5 1.678000 5.12
✅ 关键优势:
完全动态:无需预设字段层数,自动适配任意嵌套深度;
健壮可靠:正则 \[''(\w+)''\] 精准匹配合法字段名,避免字符串索引越界或引号解析错误;
向量化高效:利用 Pandas 内置方法,比循环+ast.literal_eval或手动 split 快数倍;
易扩展:通过修改 column_mapping 字典即可调整前 N 列语义(如增加 sub-parent),后续列自动归为 field。
⚠️ 注意事项:
路径中若含非 \w+ 字符(如连字符、点号),需调整正则为 r"\[''([^''\]]+)''\]" 并注意 SQL/CSV 导出时的转义;
若需严格对齐列数(如补空字符串而非 NaN),可在最后调用 .fillna('''');
实际项目中建议封装为函数,接收 values_changed 字典和可选列名映射,提升复用性。
此方法将路径解析从“字符串手术”升级为“结构化提取”,是构建可维护文档差异分析流水线的核心实践。
下一篇:没有了


