Python 为什么groupby().transform()需要唯一索引?

Python 为什么groupby().transform()需要唯一索引?,python,pandas,Python,Pandas,我想使用groupby().transform()对(排序)数据集中的每个记录块进行自定义(累积)转换。除非我确保我有唯一的钥匙,否则它不会工作。为什么? 下面是一个玩具示例: df = pd.DataFrame([[1,1], [1,2], [2,3], [3,4], [3,5]], columns='a b'.s

我想使用groupby().transform()对(排序)数据集中的每个记录块进行自定义(累积)转换。除非我确保我有唯一的钥匙,否则它不会工作。为什么?

下面是一个玩具示例:

df = pd.DataFrame([[1,1],
                  [1,2],
                  [2,3],
                  [3,4],
                  [3,5]], 
                  columns='a b'.split())
df['partials'] = df.groupby('a')['b'].transform(np.cumsum)
df
给出了预期的:

     a   b   partials
0    1   1   1
1    1   2   3
2    2   3   3
3    3   4   4
4    3   5   9
但如果“a”是一把钥匙,那么一切都会出错:

df = df.set_index('a')
df['partials'] = df.groupby(level=0)['b'].transform(np.cumsum)
df

---------------------------------------------------------------------------
Exception                                 Traceback (most recent call last)
<ipython-input-146-d0c35a4ba053> in <module>()
      3 
      4 df = df.set_index('a')
----> 5 df.groupby(level=0)['b'].transform(np.cumsum)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/groupby.pyc in transform(self, func, *args, **kwargs)
   1542             res = wrapper(group)
   1543             # result[group.index] = res
-> 1544             indexer = self.obj.index.get_indexer(group.index)
   1545             np.put(result, indexer, res)
   1546 

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/core/index.pyc in get_indexer(self, target, method, limit)
    847 
    848         if not self.is_unique:
--> 849             raise Exception('Reindexing only valid with uniquely valued Index '
    850                             'objects')
    851 

Exception: Reindexing only valid with uniquely valued Index objects
但如果您转换整个数据帧,则可以使其工作,如:

df.groupby(level=0).transform(np.cumsum)
甚至是一列数据帧(而不是系列):


我觉得我还缺少一些深层次的东西。有人能帮我澄清一下吗?

这是一个bug,因为在pandas中修复了它(当然是在0.15.2中,IIRC在0.14中修复了),所以您不应该再看到这个异常


作为一种解决方法,在早期版本中,您可以使用:

您可以将其分配给df中的一列

In [12]: df['partial'] = g.apply(np.cumsum)

是的,这就是我想要的——a群中b的部分和。我澄清了上面的说明。在我的实际示例中,“a”是一个时间戳,b是其他一些键,因此我的数据集实际上是不同长度的时间序列的集合(在时间上重叠,在组内和组间包含重复的时间戳)。我正在使用transform()对每个时间序列段进行累积操作,如移动平均等。很酷,谢谢-我想我不明白apply()和transform()之间的区别。转换是否更具限制性???@Patricksury我想知道这是否是一个bug,它看起来确实应该适合转换类别…@Patricksury transform希望组中的所有内容都有一个结果,而apply希望组中的每一行都有一个值。虽然这两种行为都是组(子数据帧)的行为,所以有点混乱。这是有道理的,但似乎并没有很清楚的记录。例如,它首先将转换描述为应用的一种形式,然后使它们听起来几乎是等效的:“……对于这些,使用应用函数,它可以在许多标准用例中替代聚合和转换。然而,应用可以处理一些特殊的用例,例如……”
df.groupby(level=0)[['b']].transform(np.cumsum)
In [10]: g = df.groupby(level=0)['b']

In [11]: g.apply(np.cumsum)
Out[11]:
a
1    1
1    3
2    3
3    4
3    9
dtype: int64
In [12]: df['partial'] = g.apply(np.cumsum)