首页 > 编程问答 >如何在包含嵌套列表列表的 json 上使用 json_normalize

如何在包含嵌套列表列表的 json 上使用 json_normalize

时间:2024-07-30 04:22:31浏览次数:11  
标签:python json pandas dataframe json-normalize

我正在用 Python 处理一个复杂的 JSON 字符串,并且在将数据放入 Pandas 数据帧时遇到问题。示例数据、当前输出和预期输出全部如下。我正在尝试使用 json_normalize,但它没有完全标准化,留下了几列包含 JSON 列表。我的最终目标是将其插入到 SQL DB 中,但是 json 字符串由于其长度而被截断,因此我无法使用我最初的计划使用 OPENJSON() 在 SQL 中执行转换。

我的 json_normalize 看起来像下面这样。使用 max_level=10 适用于我为此资源进行的所有其他 API 调用(除此特定表外)。我也尝试过按列列出它,但我的尝试失败了。

incomingJson = json.loads(incomingString)
incomingDataFrame = pd.json_normalize(incomingJson, 'fields', max_level=10)

incomingString 看起来像下面的 json。这是虚拟数据,只是为了澄清。


{
    "fields": [
        {
            "id": 12345,
            "description": "Location",
            "choices": [
                {
                    "id": 1,
                    "name": "Seattle"
                },
                {
                    "id": 2,
                    "name": "Nashville"
                }
            ],
            "other_choices": []
        },
        {
            "id": 67372,
            "description": "Name",
            "choices": [
                {
                    "id": 101,
                    "name": "John"
                },
                {
                    "id": 102,
                    "name": "Mary"
                }
            ],
            "other_choices": []
        },
        {
            "id": 39265,
            "description": "Department",
            "choices": [
                {
                    "id": 143,
                    "name": "IT"
                },
                {
                    "id": 226,
                    "name": "HR"
                },
                {
                    "id": 394,
                    "name": "ERG"
                }
            ],
            "other_choices": [
                {
                    "id": 9473
                }
            ]
        }
    ]
}

当我运行代码时,我得到如下所示的输出。

id 描述 选项 other_choices
12345 地点 [{"id": 1, "name": "西雅图"}, {"id": 2, "name": "纳什维尔"}] []
67372 名称 [{"id": 101, "name": "John"}, {"id": 102, "name": "Mary"}] []
39265 部门| ||{"id": 143, "name": "IT"}, {"id": 226, "name": "HR"}, {"id": 394, "name": "ERG"}| ||[{"id": 9473}] 我期望输出更类似于下表 id

描述

choices.id choices.name other_choices。 id 12345 位置
1 西雅图 12345 位置
2 纳什维尔 67372 姓名
101 约翰| ||67372 姓名 102
玛丽 39265 部门 143
IT 9473 39265 部门 226
HR 9473 39265 部门 394
ERG 9473 任何和所有帮助表示赞赏。 ERG 9473

Any and all help is appreciated.


由于 JSON 的结构,无法使用 json_normalize 获得所需的精确输出。但是,我们可以通过几个步骤来实现想要的结果:

import pandas as pd
import json

incomingString = '''
{"fields": [
    {
        "id": 12345,
        "description": "Location",
        "choices": [
            {
                "id": 1,
                "name": "Seattle"
            },
            {
                "id": 2,
                "name": "Nashville"
            }
        ],
        "other_choices": []
    },
    {
        "id": 67372,
        "description": "Name",
        "choices": [
            {
                "id": 101,
                "name": "John"
            },
            {
                "id": 102,
                "name": "Mary"
            }
        ],
        "other_choices": []
    },
    {
        "id": 39265,
        "description": "Department",
        "choices": [
            {
                "id": 143,
                "name": "IT"
            },
            {
                "id": 226,
                "name": "HR"
            },
            {
                "id": 394,
                "name": "ERG"
            }
        ],
        "other_choices": [
            {
                "id": 9473
            }
        ]
    }
]}
'''
incomingJson = json.loads(incomingString)

# 1. 为 "fields" 中的每个元素创建单独的数据帧。
dfs = []
for field in incomingJson['fields']:
    df = pd.DataFrame(field)
    df = df.explode('choices').explode('other_choices').reset_index(drop=True)
    dfs.append(df)

# 2. 合并创建的数据帧。
final_df = pd.concat(dfs, ignore_index=True)

# 3. 使用 "choices" 和 "other_choices" 中的字典创建新列。
final_df['choices.id'] = final_df['choices'].apply(lambda x: x.get('id') if isinstance(x, dict) else None)
final_df['choices.name'] = final_df['choices'].apply(lambda x: x.get('name') if isinstance(x, dict) else None)
final_df['other_choices.id'] = final_df['other_choices'].apply(lambda x: x.get('id') if isinstance(x, dict) else None)

# 4. 删除原始的 "choices" 和 "other_choices" 列。
final_df = final_df.drop(['choices', 'other_choices'], axis=1)

print(final_df)

这将输出以下数据帧:

       id description  choices.id choices.name  other_choices.id
0  12345    Location         1.0      Seattle               NaN
1  12345    Location         2.0    Nashville               NaN
2  67372        Name       101.0         John               NaN
3  67372        Name       102.0         Mary               NaN
4  39265   Department       143.0          IT            9473.0
5  39265   Department       226.0          HR            9473.0
6  39265   Department       394.0         ERG            9473.0

此数据帧现在具有需要的结构,可以更轻松地将其插入到 SQL 数据库中。

说明:

  1. 我们遍历 "fields" 列表中的每个元素,并为每个元素创建一个单独的数据帧。
  2. 我们使用 explode 函数将 "choices" 和 "other_choices" 列中的列表项扩展为单独的行。
  3. 我们使用 concat 函数将所有创建的数据帧合并为一个。
  4. 我们使用 apply 函数和 lambda 表达式从 "choices" 和 "other_choices" 列中的字典中提取 "id" 和 "name" 值,并将它们存储在新列中。
  5. 最后,我们删除原始的 "choices" 和 "other_choices" 列。

这是一种将嵌套 JSON 数据转换为 Pandas 数据帧的更灵活的方法,可以根据需要调整它。

标签:python,json,pandas,dataframe,json-normalize
From: 78808617

相关文章

  • python - 面板库 - PasswordInput 不会对回车做出反应
    我试图避免需要提交按钮。以下代码当前正在远程jupyter实验室运行。仅当光标焦点从密码小部件中移除后,才会打印该消息。我想要回车来触发消息打印。有什么线索吗?frompanel.widgetsimportPasswordInput,TextInputpn.extension()defon_enter(event=None):message_p......
  • pandas read_sql 导致值错误:“年份 -10100 超出范围”由数据库中的日期损坏引起
    我正在运行一个脚本将数据从oracle迁移到postgres。运行以下命令时df=pd.read_sql(query,oracle_conn,)会导致错误ValueError:year-10100isoutofrange对于跨越数千的某些行,有些日期已损坏并且年份数字很大。例如,下面是损坏的日期,而下一......
  • 即使安装了软件包,也找不到 python 模块句子转换器
    对于我的python脚本(如下所示),我使用句子转换器包,其中包含SBERT模型。即使在执行“piplist”时明确列出该软件包,并且还安装了torch,所有内容都更新到最新版本,但仍然找不到该模块。脚本:importnumpyasnpimportpandasaspdfromsentence_transformersimportSenten......
  • 有没有办法在 python 中返回类实例的布尔属性?
    我想组织我玩的游戏中的汽车数据。为此,我创建了一个“Car”类。我希望将此类实例的一些属性作为布尔值,这样我就可以将此类的所有实例放入列表中并过滤它们。我当前的解决方案不起作用,因为,我收到以下错误消息:TypeError:__repr__returnednon-string(typeCar)我使用......
  • python 正则表达式匹配一行中的多个单词而不转到下一行
    我正在编写一个解析器来解析以下输出:admin@str-s6000-on-5:~$showinterfacestatusEthernet4InterfaceLanesSpeedMTUAliasVlanOperAdminTypeAsymPFC------------------------------------------......
  • 使用 Python 平滑和对称不规则形状和曲线
    我需要完成三项任务:正则化曲线曲线的对称性完成不完整的曲线例如,这里是输入和预期的输出图像:输入输出|||在一般设置中,形状可以由任何SVG曲线基元(贝塞尔曲线、直线、弧线)表示。为了统一表示,示例包含曲线的折线近似。这些折线保存为......
  • 在Python中通过绝对路径引用数据文件夹
    我有一个大型python项目,其中数据太大,无法每次都以相同的方式共享。不同的人可能会使用网络位置或将某些内容复制到本地驱动器。该路径由不同子文件夹中的脚本和笔记本使用。例如,我将创建一个config.py来定义数据文件夹的路径。importsyssys.path.append('../'......
  • python三天速成记(看完你就会)day3 满满干货~
    续上文啦~EXCEL表的操作上一篇文章讲了怎么读取和操作txt和csv文档,但其实我们生活中还有一个常用的文本格式那就是excel文件,特别是在对大量数据进行处理的时候。excel文件的用处和广泛。其实在python中有很多库可以处理excel文件,但是本文主要介绍使用最实用最广泛的库pan......
  • Unity数据持久化——序列化/二进制/Json/PlayerPrefs
    序列化序列化是指把对象转换为字节序列的过程,而反序列化是指将字节序列恢复为对象的过程。序列化最主要的用途就是传递对象和保存对象。在Unity中保存和加载、prefab、Scene、Inspector窗口、实例化预制体等都使用了序列化和反序列化。下面是一个序列化和反序列化的例子......
  • Python输入验证改进的其他方式
    题目[题目来源:Python编程快速上手——让繁琐工作自动化(第二版)第三章实践项目,下面的解答程序为我自己完成的,仅供参考。]编写一个名为collatz()的函数,他有一个名为number的参数。如果参数是偶数,那么collatz()就输出number//2,并返回该值。如果参数是奇数,那么collatz()就......