如何将DataFrameGroupBy对象转换为不含索引列的指定结构字典
问题描述
需要对如下DataFrame执行groupby操作:
VendorID ProductID Qty Expiring Date 123456 P789456 1195 True xyz 123456 P123456 1015 True xyz 987564 P168816 251 False xyz 123456 P900456 1222 True xyz
期望得到不含索引列的指定结构字典:
[ { 'vendorid': 123456, 'products': [ {'productid': 'P789456', 'qty': 1195}, {'productid': 'P123456', 'qty': 1015}, {'productid': 'P900456', 'qty': 1222} ], 'expiring': True, 'date': 'xyz' }, { 'vendorid': 987564, 'products': [ {'productid': 'P168816', 'qty': 251}, ], 'expiring': False, 'date': 'xyz' } ]
尝试以下代码时报错:
df = df.groupby('vendorid')[['productid', 'qty', 'expiring', 'date']] df = df.apply(lambda x: x.set_index('productid').to_dict(orient='index')).to_dict()
解决思路与代码
原代码问题分析
- 列名不匹配:原DataFrame列名是大写(
VendorID、ProductID等),代码中用小写列名会直接触发KeyError,这是报错的核心原因。 - 结构逻辑错误:
set_index('productid').to_dict(orient='index')会生成以产品ID为键的字典结构,和期望的数组格式完全不符。
正确实现方案
方案一:循环分组处理
# 先统一列名为小写,匹配目标字典的键名 df.columns = df.columns.str.lower() result = [] # 按vendorid分组遍历 for vendor_id, group in df.groupby('vendorid'): # 提取每组的expiring和date(假设同一供应商下这两个值唯一) expiring_status = group['expiring'].iloc[0] record_date = group['date'].iloc[0] # 直接将productid和qty转换为目标列表结构 product_list = group[['productid', 'qty']].to_dict('records') # 组合成目标字典并加入结果列表 result.append({ 'vendorid': vendor_id, 'products': product_list, 'expiring': expiring_status, 'date': record_date }) print(result)
方案二:用groupby.apply简化实现
df.columns = df.columns.str.lower() result = (df.groupby('vendorid') .apply(lambda g: { 'vendorid': g.name, # g.name就是当前分组的vendorid值 'products': g[['productid', 'qty']].to_dict('records'), 'expiring': g['expiring'].iloc[0], 'date': g['date'].iloc[0] }) .tolist()) # 将分组结果转为列表 print(result)
关键说明
- 列名统一:把原DataFrame的大写列名转为小写,避免键名匹配错误。
to_dict('records'):这个参数会将DataFrame的每一行转换为一个字典,直接生成products需要的列表结构,无需手动拼接。- 唯一值提取:假设同一供应商的
expiring和date值唯一,因此用iloc[0]取第一个值;如果存在多值情况,需要额外处理(比如取唯一值或抛出异常)。
内容的提问来源于stack exchange,提问作者iPaul
相关产品推荐
相关产品推荐

