如何将pandas中包含嵌套字典列表的列转换为多行数据?
pandas嵌套字典列表列展开为多行的实现方法
需求说明
我有一个pandas DataFrame,其中一列存储的是嵌套字典组成的列表,示例数据构造代码如下:
import pandas as pd import numpy as np df = pd.DataFrame({"Column_1" : [ [{'PID': '03', 'Col_par': [{'PID': '01', 'mace': [{'all': 100, 'd_Loc': 'front'}]}]}], np.nan, [{'PID': '01', 'Col_par': [{'PID': '02', 'mace': [{'all': 100, 'd_Loc': 'driver side'}]}]}], [{'PID': '01', 'Col_par': [{'PID': '11', 'mace': [{'all': 0, 'd_Loc': 'front'}]}, {'PID': '14', 'mace': [{'all': 23, 'd_Loc': 'rear'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}]}]}, {'PID': '06', 'Col_par': [{'PID': '11', 'mace': [{'all': 0, 'd_Loc': 'front'}]}, {'PID': '01', 'mace': [{'all': 0, 'd_Loc': 'front'}]}, {'PID': '14', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '10', 'mace': [{'all': 0, 'd_Loc': 'rear'}]}]}, {'PID': '14', 'Col_par': [{'PID': '11', 'mace': [{'all': 0, 'd_Loc': 'front'}]}, {'PID': '01', 'mace': [{'all': 0, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 25, 'd_Loc': 'rear'}, {'all': 100, 'd_Loc': 'front'}]}, {'PID': '10', 'mace': [{'all': 100, 'd_Loc': 'rear'}]}]}, {'PID': '11', 'Col_par': [{'PID': '01', 'mace': [{'all': 100, 'd_Loc': 'front'}]}, {'PID': '14', 'mace': [{'all': 53, 'd_Loc': 'rear'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}]}]}, {'PID': '10', 'Col_par': [{'PID': '14', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}]}], [{'PID': '03', 'Col_par': [{'PID': '01', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '09', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}]}, {'PID': '06', 'Col_par': [{'PID': '01', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '03', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '09', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}]}, {'PID': '08', 'Col_par': [{'PID': '01', 'mace': [{'all': 100, 'd_Loc': 'rear'}, {'all': 100, 'd_Loc': 'front'}]}, {'PID': '03', 'mace': [{'all': 100, 'd_Loc': 'rear'}, {'all': 100, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 100, 'd_Loc': 'rear'}, {'all': 100, 'd_Loc': 'front'}]}, {'PID': '09', 'mace': [{'all': 100, 'd_Loc': 'rear'}, {'all': 100, 'd_Loc': 'front'}]}]}, {'PID': '09', 'Col_par': [{'PID': '01', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '03', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}]}, {'PID': '01', 'Col_par': [{'PID': '03', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '06', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}, {'PID': '09', 'mace': [{'all': 0, 'd_Loc': 'rear'}, {'all': 0, 'd_Loc': 'front'}]}]}]], "Key" : [1, 2, 3, 4, 5], "Val_1": [25, 46, 75, 85, 89]})
当前数据预览:
Column_1 Key Val_1 0 [{'PID': '03', 'Col_par': [{'PID': '01', 'mace... 1 25 1 NaN 2 46 2 [{'PID': '01', 'Col_par': [{'PID': '02', 'mace... 3 75 3 [{'PID': '01', 'Col_par': [{'PID': '11', 'mace... 4 85 4 [{'PID': '03', 'Col_par': [{'PID': '01', 'mace... 5 89
我需要提取嵌套字典中的对应字段值,将嵌套字典列表结构展开为独立的行,目标输出格式如下:
PID_Val, Col_par_PID, PID_mace_all, PID_d_loc, Key, Val1 '03', '01', 100, 'front', 1, 25 np.nan, np.nan, np.nan, np.nan, 2, 46 '01', '02', 100,'driver side', 3, 75 '01', '11', 0, 'front', 4, 85 '01', '14', 23, 'rear', 4, 85 '01', '06', 0, 'rear', 4, 85 '06', '11', 0, 'front', 4, 85 '06', '01', 0, 'front', 4, 85 '06', '14', 0, 'rear', 4, 85 # 其余行以此类推
实现方案
核心思路是通过explode逐层展开嵌套的列表结构,配合json_normalize解析字典字段,全程保留原有行的Key和Val_1字段关联:
# 第一层展开:展开Column_1最外层的列表 df_explode1 = df.explode('Column_1', ignore_index=False) # 解析第一层字典,提取PID_Val字段,保留原有索引关联其他字段 df_level1 = pd.json_normalize(df_explode1['Column_1']).set_index(df_explode1.index) df_level1 = df_level1.rename(columns={'PID': 'PID_Val'}) # 合并原表的Key、Val_1字段 df_merged1 = pd.concat([df_level1, df[['Key', 'Val_1']]], axis=1) # 第二层展开:展开Col_par列表 df_explode2 = df_merged1.explode('Col_par', ignore_index=False) # 解析第二层字典,提取Col_par_PID字段 df_level2 = pd.json_normalize(df_explode2['Col_par']).set_index(df_explode2.index) df_level2 = df_level2.rename(columns={'PID': 'Col_par_PID'}) df_merged2 = pd.concat([df_explode2.drop('Col_par', axis=1), df_level2], axis=1) # 第三层展开:展开mace列表 df_explode3 = df_merged2.explode('mace', ignore_index=False) # 解析第三层字典,提取对应字段并改名 df_level3 = pd.json_normalize(df_explode3['mace']).set_index(df_explode3.index) df_level3 = df_level3.rename(columns={'all': 'PID_mace_all', 'd_Loc': 'PID_d_loc'}) # 合并得到最终结果,按目标顺序重排列 final_df = pd.concat([df_explode3.drop('mace', axis=1), df_level3], axis=1) final_df = final_df[['PID_Val', 'Col_par_PID', 'PID_mace_all', 'PID_d_loc', 'Key', 'Val_1']].reset_index(drop=True)
运行后输出final_df即可得到符合要求的展开结果,原NaN行也会保留所有字段为NaN值。
内容的提问来源于stack exchange,提问作者Ailurophile
相关产品推荐
相关产品推荐

