You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python JSON嵌套结构归一化:实现按outcome.id生成唯一记录的DataFrame

处理嵌套JSON并生成指定结构的DataFrame

问题场景

我正在学习处理复杂的JSON嵌套结构,想要把它加载成DataFrame,要求每个outcome.id对应一条唯一记录。示例JSON和期望的DataFrame格式如下:

示例JSON结构

{
  "_id": 12345,
  "reports": [
    {
      "body": "\n***\nGeneral report text.",
      "outcome": {
        "comments": [],
        "id": "1",
        "status": {
          "failed": { "both": 0, "human": 0, "auto": 0, "total": 0 },
          "open": { "both": 0, "human": 0, "auto": 0, "total": 0 },
          "passed": { "both": 0, "human": 0, "auto": 1, "total": 1 },
          "code": { "_input": 0, "_output": 0, "canceled": 0 },
          "total": 1
        }
      },
      "type": "outcome"
    },
    {
      "body": "\n***\nGeneral report text.",
      "outcome": {
        "comments": [],
        "id": "2",
        "status": {
          "failed": { "both": 0, "human": 0, "auto": 0, "total": 0 },
          "open": { "both": 0, "human": 0, "auto": 0, "total": 0 },
          "passed": { "both": 0, "human": 0, "auto": 1, "total": 1 },
          "code": { "_input": 0, "_output": 0, "canceled": 0 },
          "total": 1
        }
      },
      "type": "outcome"
    }
  ]
}

期望的DataFrame格式

report_idoutcome.idbodyoutcome.commentsstatus.failed.bothstatus.failed.human...

我之前尝试了这段代码,但没得到预期结果:

df_reports = pd.json_normalize(data,record_path=['reports', 'outcome'], meta=[ ['reports','body'], ['outcome','comment'], ['outcome','id'], ['outcome','status'] ])

解决方案

问题出在json_normalize的参数配置上——你把record_path设到了outcome层级,同时meta里的路径又重复引用了outcome的字段,导致结构混乱。咱们调整一下参数,让工具自动帮我们展开嵌套结构:

正确实现代码

import pandas as pd

# 假设你的JSON数据已经存放在data变量中
df_reports = pd.json_normalize(
    data,
    record_path='reports',  # 先遍历每个reports条目,每个条目对应一条记录
    meta='_id',  # 把顶层的_id关联到每条记录,作为report_id
    sep='.'  # 用点号分隔嵌套字段,和你期望的列名格式匹配
)

# 把顶层的_id列重命名为report_id
df_reports.rename(columns={'_id': 'report_id'}, inplace=True)

# 如果想去掉outcome.前缀,执行下面这行
# df_reports.columns = df_reports.columns.str.replace('outcome.', '', regex=False)

# 查看最终结果
print(df_reports.head())

代码说明

  1. record_path='reports':这一步是关键——我们让json_normalize先遍历reports数组里的每个元素,每个元素正好对应一个outcome.id,完美匹配“一条记录对应一个outcome.id”的要求。
  2. meta='_id':把JSON顶层的_id字段添加到每条记录里,后续重命名成你要的report_id
  3. sep='.':指定嵌套字段用点号连接,这样outcome.status.failed.both会自动生成为对应的列名,完全符合你想要的格式。

运行后你会得到包含所有状态字段的DataFrame,每个outcome.id对应唯一一行,和你期望的结构完全一致。


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

火山引擎 最新活动