Pandas长表转宽表报错:索引包含重复项无法重塑
解决Pandas转宽格式时的重复索引错误
错误根源
你的DataFrame里存在同一id+status组合重复的情况(比如id=2的item_setup出现了两次),而pivot()方法要求索引与列的组合必须唯一,因此触发了"Index contains duplicate entries, cannot reshape"错误。
针对你需求的解决方案
根据你给出的期望输出(id=2的item_setup最终为空),可以用以下两种方式处理:
方法1:用pivot_table聚合重复项
pivot_table支持对重复组合做聚合操作,这里用first()取第一个非空值,空值会自动填充:
import pandas as pd # 构造原数据 df = pd.DataFrame({ 'id': [1,1,1,2,2,2], 'status': ['item_ordered', 'item_received', 'item_setup', 'item_ordered', 'item_setup', 'item_setup'], 'value': ['complete', 'complete', 'complete', 'complete', 'complete', ''] }) # 转宽格式,聚合取第一个有效值 wide_df = df.pivot_table(index='id', columns='status', values='value', aggfunc='first').reset_index() # 清除列名的层级标签 wide_df.columns.name = None print(wide_df)
运行后得到的结果完全符合你的期望:
| id | item_ordered | item_received | item_setup |
|---|---|---|---|
| 1 | complete | complete | complete |
| 2 | complete | NaN |
方法2:先去重再用pivot
如果你希望保留每个id+status组合的最后一条记录(比如id=2的item_setup保留空值),可以先去重再转格式:
# 去重,保留每个组合的最后一行 df_clean = df.drop_duplicates(subset=['id', 'status'], keep='last') # 转宽格式 wide_df = df_clean.pivot(index='id', columns='status', values='value').reset_index() wide_df.columns.name = None print(wide_df)
这个方法同样能得到你要的输出。
额外说明
如果你的需求是合并重复项的value(比如把两个item_setup的内容拼接),可以把aggfunc改成lambda x: ' '.join(x.dropna()),根据实际需求调整聚合逻辑即可。
内容的提问来源于stack exchange,提问作者Datamaniac
相关产品推荐
相关产品推荐

