You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:将展平后的单层Pandas DataFrame转换为动态层级DataFrame

求助:将展平后的单层Pandas DataFrame转换为动态层级DataFrame

我完全懂你现在的困扰——已经把嵌套JSON展平成列名用点分隔的单层DataFrame了,但想把它转回适配任意嵌套深度的层级结构,之前试的循环拼接方法还全是NaN,确实头疼!我来帮你理清思路,给出能动态适配的解决方案。

先明确你的需求

先把你的示例数据和期望输出再理清楚,方便对照:

原始嵌套JSON

{"rr":{"bp": {
"0": "0 - 10",
"1": "10 - 20",
"2": "20 - 30"
},
"al": {
"0": 11.8,
"1": 77.2,
"2": 98.4
}}
}

已展平的单层DataFrame

rr.bp.0rr.bp.1rr.bp.2rr.al.0rr.al.1rr.al.2
00 - 1010 - 2020 - 3011.877.298.4

期望的动态层级DataFrame

Header0Header1012
rrbp0 - 1010 - 2020 - 30
rral11.877.298.4

为什么你之前的循环代码会出NaN?

你写的循环逻辑里,每次创建的temp_df用了单独的MultiIndex列和单个值,但拼接的时候没有对齐数据结构——比如每次的index是0、1这种单个键,而列是('rr','bp')这种层级,多次concat后自然会因为索引和列不匹配出现NaN,这种逐个处理的方式很难对齐结构,不如用Pandas原生的层级索引操作来高效解决。

动态适配的解决方案(支持任意嵌套深度)

核心思路是:利用列名的点分隔拆分出层级,通过Pandas的MultiIndex、stack、unstack来批量转换,完全不需要循环拼接,而且能自动适配不同的嵌套深度。

完整代码示例

import pandas as pd
import re

# 1. 示例展平后的DataFrame(你可以替换成自己的实际数据)
flattened_df = pd.DataFrame({
    "rr.bp.0": ["0 - 10"],
    "rr.bp.1": ["10 - 20"],
    "rr.bp.2": ["20 - 30"],
    "rr.al.0": [11.8],
    "rr.al.1": [77.2],
    "rr.al.2": [98.4]
})

# 2. 计算最大嵌套深度:列名中点的数量(比如rr.bp.0有2个点,对应3级层级)
max_depth_list = [len(re.findall('\.', col)) for col in flattened_df.columns]
max_depth = max(max_depth_list)

# 3. 转换为动态层级DataFrame
hierarchical_df = (
    flattened_df
    # 把单层列名按点拆分,转换为MultiIndex列(层级自动对应嵌套结构)
    .set_axis(flattened_df.columns.str.split(".", expand=True), axis=1)
    # 将前(max_depth-1)层列索引转为行索引(保留最后一层作为值的列)
    .stack(list(range(max_depth - 1)))
    # 把最后一层的索引(比如0、1、2)转为列
    .unstack()
    # 移除原始的行索引(示例中是0)
    .droplevel(0)
    # 给层级行索引命名为Header0、Header1...
    .rename_axis([f"Header{i}" for i in range(max_depth - 1)])
    # 把层级索引转为普通列,重置索引
    .reset_index()
)

print(hierarchical_df)

代码逐行解释

  1. 拆分列名为MultiIndex:flattened_df.columns.str.split(".", expand=True)会把rr.bp.0拆成('rr', 'bp', '0')这样的三层列索引,完美对应原始JSON的嵌套结构。
  2. stack转层级为行:stack(list(range(max_depth - 1)))把前两层(rr、bp/al)从列索引转到行索引,让同一组的数值归到同一行。
  3. unstack转叶子键为列:把最底层的键(0、1、2)从行索引转回列,就是你期望的数值列。
  4. 整理索引:最后去掉多余的原始行索引,给层级索引命名,再转成普通列,就得到了干净的层级DataFrame。

适配更深嵌套的情况

比如如果你的JSON是{"a":{"b":{"c":{"0":1,"1":2}}}},展平后列名是a.b.c.0、a.b.c.1,这段代码也能自动识别max_depth=3,生成Header0、Header1、Header2作为层级列,0、1作为数值列,完全动态适配。

备注:内容来源于stack exchange,提问作者Turumella Aditya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 13:49:39