有没有办法用不同数量的对象展平嵌套 json 字符串的 pandas 列?

Is there a way to flatten a pandas column of nested json strings with a varying number of objects?

提问人:user19462600 提问时间:11/6/2023 更新时间:11/6/2023 访问量:41

问:

我有一个 pandas 数据帧,其格式类似于:

order_guid 选择
EF23A23D-5E2C-42A0-952B-CF43732C55B8 [{“id”:“7233”,“item”:“冰沙”},{“guid”:“6317”,“item”:“果汁”},{“guid”:“6941”,“item”:“薯片”}]
0FB69525-7B71-4DEC-AB77-36A698D519F6 [{“id”:“5425”,“item”:“换行”}]
59b5f8e9-96f1-483b-a31d-659492765e06 [{“id”:“7233”,“item”:“冰沙”},{“guid”:“3803”,“item”:“水”},{“guid”:“7961”,“item”:“沙拉”}]
D8656BA2-4076-4036-9515-6FEA1F9E58D4 [{“id”:“7961”,“item”:“沙拉”},{“guid”:“5425”,“item”:“换行”}]

我一直在尝试做的是取消嵌套该字段,以便每个选择都占据自己的行,并将 作为外键添加到单独的表中,类似于以下内容:selectionsorder_guidorders

order_guid selection_id selection_item
EF23A23D-5E2C-42A0-952B-CF43732C55B8 7233 水果奶昔
EF23A23D-5E2C-42A0-952B-CF43732C55B8 6317
EF23A23D-5E2C-42A0-952B-CF43732C55B8 6941 芯片
0FB69525-7B71-4DEC-AB77-36A698D519F6 5425 包装
59b5f8e9-96f1-483b-a31d-659492765e06 7233 水果奶昔
59b5f8e9-96f1-483b-a31d-659492765e06 3803
59b5f8e9-96f1-483b-a31d-659492765e06 7961 沙拉
D8656BA2-4076-4036-9515-6FEA1F9E58D4 7961 沙拉
D8656BA2-4076-4036-9515-6FEA1F9E58D4 5425 包装

给我带来麻烦的主要因素是嵌套的 json 元素数量不同。我最初的直觉是我可以做一些类似 ->-> 的事情,但我不能用 和 多重选择来做到这一点。循环似乎很傻。感觉这是一个足够简单的问题,其他人应该遇到它,但这是我见过的最接近这个问题的问题。to_json()json.loads()json_normalizeorder_guid

有熊猫的方法吗?还是我错过了什么明显的东西?

python json pandas nested-json

评论

1赞 Nick 11/6/2023
为什么有些选择项目有其他选择?idguid
0赞 Nick 11/6/2023
列中的值是字典列表还是 JSON 列表?selections
0赞 wjandrea 11/6/2023
@Nick 根据它们的格式,它们看起来像是字符串,加上 OP 在标题中说“json 字符串”。
0赞 wjandrea 11/6/2023
相关新闻: 使用 pandas 拆分/分解一列词典到单独的列

答:

1赞 Sharat 11/6/2023 #1

您可以先使用后再使用。希望这就是你的意思。df.explode()json_normalize()

df = df.explode('selections').reset_index(drop=True)
result_df = pd.concat([df['order_guid'], pd.json_normalize(df.selections)], axis=1)
result_df['guid'] = result_df['guid'].fillna(result_df['id'])
result_df = result_df[['order_guid', 'guid', 'item']].rename(columns={'guid': 'selection_guid', 'item': 'selection_item'})

评论

0赞 user19462600 11/6/2023
df.explode虽然我的其余代码略有不同,但它对我有用,所以我坚持下去。 感谢您的帮助!你让我免于(更长的)头痛。df = df.explode('checks.selections').reset_index(drop=True) df_json = df.to_json(orient="records") df_load = json.loads(df_json) df_normalized = pd.json_normalize(df_load)
0赞 user19462600 11/7/2023
更新:我的第一条评论中的代码有效*,但我实际上最终只使用了您代码的前行。我第一次尝试实现它时一定犯了一些错误。* 我刚刚意识到这遗漏了请求的一个关键部分;这order_guid