正如几个答案所指出的,问题不在于您的索引中有重复的值(错误消息在这里肯定没有帮助),而是您有重复的(index, column)
. 一些答案建议您只删除这些重复项,但我会小心这样做 - 根据我的经验,这很少是正确的选择。通常情况下,您可能希望以某种方式聚合您的数据,然后进行透视。
我从这篇博文中提取了一些例子和引用,我建议你阅读下面的更多细节。
给定这样的数据:
df = pd.DataFrame([
['a', 'x', 1],
['a', 'x', 2],
['b', 'x', 3],
['b', 'y', 4]
], columns=['g1', 'g2', 'value'])
打印如下:
>>> print(df)
g1 g2 value
0 a x 1
1 a x 2
2 b x 3
3 b y 4
我们ValueError
在尝试使用g1
索引和g2
列进行旋转时得到一个:
>>> df.pivot(index='g1', columns='g2', values='value')
...
ValueError: Index contains duplicate entries, cannot reshape
g1
请注意,第 0 行和第 1 行的和g2
:具有相同的值(a, x)
。因此,当 pandas 为a
索引、g1
列创建旋转数据框时,如何只选择一个值:1 或 2?答案是……我们不能!这就是删除重复项有效的原因,但它可能不是您想要的,因为您正在丢失可能有用的数据。那么我们能做些什么呢?
解决方案 1:聚合
并不总是有一个对您的用例有意义的聚合函数,但如果有的话,有几种方法可以实现这一点。
df.pivot_table(index='g1', columns='g2', values='value', aggfunc='sum')
df_agg = df.groupby(by=['g1', 'g2']).value.sum().reset_index()
df_agg.pivot(index='g1', columns='g2', values='value')
df.groupby(by=['g1', 'g2']).value.sum().unstack()
所有这些都会产生相同的结果:
g2 x y
g1
a 3.0 NaN
b 3.0 4.0
但是,如果您不需要总和怎么办?也许逗号分隔值在您的情况下很有用?
df.pivot_table(
index='g1',
columns='g2',
values='value',
aggfunc=lambda x: ','.join(x.astype('str'))
)
# we need to convert to strings before we can join
要得到:
g2 x y
g1
a 1,2 NaN
b 3 4
或者您可以list
用作您的aggfunc
:
pv = df.pivot_table(index='g1', columns='g2', values='value', aggfunc=list)
然后我们就可以爆炸了!
>>> pv.explode('x').explode('y')
g2 x y
g1
a 1 NaN
a 2 NaN
b 3 4
解决方案 2:给自己另一把钥匙
这是基于这个答案
>>> df['key'] = df.groupby(['g1', 'g2']).cumcount()
>>> df
g1 g2 value key
0 a x 1 0
1 a x 2 1
2 b x 3 0
3 b y 4 0
现在我们可以使用复合索引进行旋转:
>>> df.pivot(index=['key', 'g1'], columns='g2', values='value').reset_index().drop(columns='key')
g2 g1 x y
0 a 1.0 NaN
1 b 3.0 4.0
2 a 2.0 NaN
这与上面分解的示例几乎相同,只是一个set_index('g1')
距离。
希望这可以帮助!我经常遇到这个问题,通常会忘记这一切..