将字典列表转换为带动态表头列的Pandas DataFrame:分组需求与报错解决
解决Pandas按ASIN和关键词分组生成动态表头DataFrame的问题
问题描述
给定以下字典列表(已修正原始数据中volume的语法错误,补充缺失值以匹配目标结构):
import pandas as pd my_lists = [ {'rank': 2, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B01MG0ORBL'}, {'rank': 18, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B0735C9RDZ'}, {'rank': 21, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B07FPVR858'}, {'rank': 126, 'keyword_name': 'mens wallet', 'volume': pd.NA, 'asin': 'B01MG0ORBL'}, {'rank': 128, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B0735C9RDZ'}, {'rank': 136, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B07FPVR858'}, {'rank': 19, 'keyword_name': 'leather wallets', 'volume': 23, 'asin': 'B0735C9RDZ'}, {'rank': 10, 'keyword_name': 'wallets for men', 'volume': 566, 'asin': 'B07FPVR858'}, {'rank': 16, 'keyword_name': 'wallets for men', 'volume': 566, 'asin': 'B0735C9RDZ'} ]
需要生成以keyword_name、volume为固定列,各ASIN值为动态表头的DataFrame,目标结构如下:
| keyword_name | volume | B01MG0ORBL | B0735C9RDZ | B07FPVR858 |
|---|---|---|---|---|
| mens wallet | 456677 | 2,126 | 18,128,19,16 | 21,10 |
| leather wallets | 23 | 19 | ||
| wallets for men | 566 | 16 | 10 |
原始代码错误分析
你遇到的TypeError: string indices must be integers主要有两个原因:
- 拼写错误:
pd.dataframe(d)应该是pd.DataFrame(d)(注意DataFrame首字母大写); - 逻辑错误:你的列表推导式
[{d['asin']:d['rank'] for d in l} for l in my_lists]遍历逻辑完全错误——my_lists里的每个元素l本身就是单个字典,遍历l实际是遍历字典的键(字符串),导致d变成字符串,自然无法用d['asin']取值,触发类型错误。
另外这段代码也没有实现按keyword_name和volume分组的核心需求,只是把每个字典转成了单键小字典,完全不符合目标结构。
解决方案代码
下面是正确实现需求的代码:
import pandas as pd # 修正后的原始数据 my_lists = [ {'rank': 2, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B01MG0ORBL'}, {'rank': 18, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B0735C9RDZ'}, {'rank': 21, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B07FPVR858'}, {'rank': 126, 'keyword_name': 'mens wallet', 'volume': pd.NA, 'asin': 'B01MG0ORBL'}, {'rank': 128, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B0735C9RDZ'}, {'rank': 136, 'keyword_name': 'mens wallet', 'volume': 456677, 'asin': 'B07FPVR858'}, {'rank': 19, 'keyword_name': 'leather wallets', 'volume': 23, 'asin': 'B0735C9RDZ'}, {'rank': 10, 'keyword_name': 'wallets for men', 'volume': 566, 'asin': 'B07FPVR858'}, {'rank': 16, 'keyword_name': 'wallets for men', 'volume': 566, 'asin': 'B0735C9RDZ'} ] # 1. 转换为初始DataFrame df = pd.DataFrame(my_lists) # 2. 按关键词、流量、ASIN分组,收集rank并转为逗号分隔的字符串 grouped = df.groupby(['keyword_name', 'volume', 'asin'])['rank']\ .apply(lambda x: ','.join(map(str, x)))\ .reset_index() # 3. 透视表转换为目标宽表结构,空值填充为空字符串 result_df = grouped.pivot(index=['keyword_name', 'volume'], columns='asin', values='rank')\ .reset_index()\ .fillna('') # 移除列名的层级标签 result_df.columns.name = None # 4. 保存到Excel文件 path = '.' # 替换为你的实际路径 writer = pd.ExcelWriter(f"{path}/sheet.xlsx", engine="xlsxwriter") result_df.to_excel(writer, sheet_name="Organic", startrow=0, header=True, index=False) writer.close() # 必须关闭writer完成文件写入
代码解释
- 修正原始数据:修复
volume的语法错误,补充缺失值以匹配目标表样式; - 初始DataFrame转换:把字典列表直接转为Pandas DataFrame,方便后续分组操作;
- 分组聚合:按
keyword_name、volume、asin分组,将同一组的rank值用逗号连接成字符串; - 透视表转换:用
pivot把ASIN转为动态表头,并用fillna('')将空值转为空字符串,贴合目标样式; - Excel保存:使用
xlsxwriter引擎写入文件,注意最后要调用writer.close()完成文件写入。
内容的提问来源于stack exchange,提问作者ira
相关产品推荐
相关产品推荐

