首页 > 解决方案 > 如何处理 ValueError:索引包含使用 df.pivot 或 pd.pivot_table 的重复条目?

问题描述

我有一张表格,显示了dataframe values不同专家 ( ID) 完成一系列四项任务所花费的累计小时数 ( ),['Task1, 'Tas2', 'Task3, 'Tas4']如下所示:

输入:

    ID  Task1   Task2   Task3   Task4
0   10      1       3       4       6
1   11      1       3       4       5
2   12      1       3       4       6

现在我想重塑那个数据框,以便我可以轻松地找出每个专家在 1 小时、2 小时等后正在处理的任务。所以所需的输出如下所示:

期望的输出:

value   1       3       4       5       6
ID                  
10  Task1   Task2   Task3   Task3   Task4
11  Task1   Task2   Task3   Task4   Task4
12  Task1   Task2   Task3   Task3   Task4

使用这个特定的数据框,我已经设法使用 , 生成所需的输出pd.melt()pd.pivot()并且pd.fillna()像这样(完整的片段和示例数据进一步向下):

我试过的:

df = pd.melt(df1, id_vars=['ID'], value_vars=df1.columns[1:])
df = df.pivot(index='ID', columns = 'value', values = 'variable')
df = df.fillna(method = 'ffill', axis = 1)

问题是这种方法不是很健壮,因为它很容易与会呈现(我认为)重复列名的数据集崩溃。这是一个示例,仅通过更改Task3for ID=0from就会发生这种情况5 to 4

代码 1

import pandas as pd
df1 = pd.DataFrame({   'ID': {0: 10, 1: 11, 2: 12},
                   'Task1': {0: 1, 1: 1, 2: 1},
                   'Task2': {0: 4, 1: 3, 2: 3},
                   'Task3': {0: 4, 1: 4, 2: 4},
                   'Task4': {0: 6, 1: 5, 2: 6}})

df = pd.melt(df1, id_vars=['ID'], value_vars=df1.columns[1:])
df = df.pivot(index='ID', columns = 'value', values = 'variable')
df = df.fillna(method = 'ffill', axis = 1)
df

代码 1 - 错误:

ValueError:索引包含重复的条目,无法重塑

根据文档pd.pivot_table()是:

可以处理一个索引/列对的重复值的枢轴的泛化。

所以我希望这pd.pivot_table()会更适合这种情况。唉,这会触发:

DataError:没有要聚合的数字类型

有谁知道是否有可能获得处理这些错误的可靠方法?我可能只是使用pd.pivot_table()了错误的方式吗?我也尝试过包括aggfunc=None.

我在这里不知所措,所以任何建议都会很棒!尽管我希望采用df.pivotorpd.pivot_table和/或尽可能最短的方法。

完整的工作代码示例:

import pandas as pd
df1 = pd.DataFrame({   'ID': {0: 10, 1: 11, 2: 12},
                   'Task1': {0: 1, 1: 1, 2: 1},
                   'Task2': {0: 4, 1: 3, 2: 3},
                   'Task3': {0: 5, 1: 4, 2: 4},
                   'Task4': {0: 6, 1: 5, 2: 6}})

df = pd.melt(df1, id_vars=['ID'], value_vars=df1.columns[1:])
df = df.pivot(index='ID', columns = 'value', values = 'variable')
df = df.fillna(method = 'ffill', axis = 1)
df

df.pivot两者都pd.pivot_table失败的完整示例:

import pandas as pd
df1 = pd.DataFrame({   'ID': {0: 10, 1: 11, 2: 12},
                   'Task1': {0: 1, 1: 1, 2: 1},
                   'Task2': {0: 4, 1: 3, 2: 3},
                   'Task3': {0: 4, 1: 4, 2: 4},
                   'Task4': {0: 6, 1: 5, 2: 6}})

df = pd.melt(df1, id_vars=['ID'], value_vars=df1.columns[1:])
# df = df.pivot(index='ID', columns = 'value', values = 'variable')

df = df.pivot_table(index='ID', columns = 'value', values = 'variable')
df = df.fillna(method = 'ffill', axis = 1)
df

标签: pythonpandas

解决方案


我很确定这不是最好的方法,但它是一种方法。

import pandas as pd
import numpy as np

df = pd.DataFrame({'ID': {0: 10, 1: 11, 2: 12},
                   'Task1': {0: 1, 1: 1, 2: 1},
                   'Task2': {0: 4, 1: 3, 2: 3},
                   'Task3': {0: 4, 1: 4, 2: 4},
                   'Task4': {0: 6, 1: 5, 2: 6}})

df1 = pd.melt(df, id_vars=['ID'], value_vars=df.columns[1:])
df1['value'] = df1['value'].astype(int)
df1.set_index(['ID','value'], inplace=True)

df_max_val = df.set_index('ID').max().max()
ids = df['ID'].tolist()*df_max_val
values = list(np.array([[i]*len(set(ids)) for i in range(1, df_max_val+1)]).flatten())
df2 = pd.DataFrame({'ID':ids,
                    'value':values})
df2.set_index(['ID','value'], inplace=True)

df3 = df2.merge(df1, left_index=True, right_index=True, how='outer')
df3 = df3.reset_index().drop_duplicates(subset=['ID','value'], keep='last')
df3 = pd.concat([df3[df3['ID']==i].fillna(method='ffill') for i in df3['ID'].unique()])
df3 = df3.pivot(index='ID', columns='value', values='variable')

推荐阅读