Pandas如何拆分字典列表类型列并展开DataFrame行
解决方案
直接按以下步骤实现即可,附可直接运行的代码和验证样例:
核心逻辑
- 直接调用
explode()展开shop列的列表,空列表展开后会自动生成NaN值,无需提前预处理空值 - 对展开后的单条字典提取目标嵌套字段,空值位置填充NA
- 筛选目标列得到最终四列长表
步骤1:构造测试验证数据
和描述的表结构完全一致,包含正常多字典列表、空列表、单字典列表三种场景:
import pandas as pd import numpy as np df = pd.DataFrame({ 'id': [1, 2, 3], 'price': [99, 199, 299], 'shop': [ [ {'code': {'location': '北京朝阳', 'guests': 200}, 'text': {'textvalue': '旗舰店'}}, {'code': {'location': '上海浦东', 'guests': 150}, 'text': {'textvalue': '分店'}} ], [], [ {'code': {'location': '广州天河', 'guests': 300}, 'text': {'textvalue': '体验店'}} ] ] })
步骤2:通用版本实现(兼容所有pandas版本,适合中小数据量)
# 展开shop列,重置索引 df_explode = df.explode('shop', ignore_index=True) # 提取嵌套字段,空值自动填充NA df_explode['shop.location'] = df_explode['shop'].apply( lambda x: x['code']['location'] if isinstance(x, dict) else np.nan ) df_explode['shop.textvalue'] = df_explode['shop'].apply( lambda x: x['text']['textvalue'] if isinstance(x, dict) else np.nan ) # 筛选目标列得到最终结果 final_df = df_explode[['id', 'price', 'shop.location', 'shop.textvalue']]
运行后输出结果:
id price shop.location shop.textvalue 0 1 99 北京朝阳 旗舰店 1 1 99 上海浦东 分店 2 2 199 NaN NaN 3 3 299 广州天河 体验店
步骤3:大数据量优化版本(10w行以上场景性能更好)
用pd.json_normalize替代逐行apply,减少遍历开销:
df_explode = df.explode('shop', ignore_index=True) # 仅对非空字典行做结构化解析 parse_part = pd.json_normalize( df_explode['shop'].dropna() )[['code.location', 'text.textvalue']] parse_part.columns = ['shop.location', 'shop.textvalue'] # 对齐原表索引后合并,空位置自动补NA final_df = pd.concat( [df_explode[['id', 'price']], parse_part.set_axis(df_explode['shop'].dropna().index)], axis=1 )
常见踩坑说明
- 不要在explode前提前遍历列表拆字段,列表长度不一致时会出现索引对齐错误
- 空列表
[]经过explode后会自动转为NaN,不需要提前把空列表替换成其他值 - 字段提取时用
isinstance(x, dict)判断比pd.notna(x)兼容性更好,避免特殊值导致的KeyError
内容的提问来源于stack exchange,提问作者Shannah
相关产品推荐
相关产品推荐

