2013-05-01 87 views
11

我想使用groupby()。transform()对(排序的)数据集中的每个记录块进行自定义(累积)变换。除非我确保我有一个唯一的密钥,否则它不起作用。为什么?为什么pandas 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 

给出预期:

,但如果 '一' 是一个关键,这一切都错了:

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 

同样的错误如果您在分组之前选择列'b',即。

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

,但你可以做,如果你改变了整个数据框,就像它的工作:

df.groupby(level=0).transform(np.cumsum) 

甚至一列数据框(而不是系列):

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

我感觉好像还有一些GroupBy-fu的深层部分,我很想念。有人能让我挺身而出吗?

+0

分配这列是的,这就是我想要的 - 'a'组中'b'的部分和。我澄清了上面的插图。在我的实际示例中,'a'是时间戳,b是其他一些键,所以我的数据集实际上是一组不同长度的时间序列(它们在时间上重叠并且在组内和组之间包含重复的时间戳)。我正在使用transform()在每个时间片段上执行累积操作,如移动平均值等。 – patricksurry 2013-05-01 10:23:06

回答

5

这是一个bug,因为固定在熊猫(当然在0.15.2,IIRC固定在0.14),所以你不应该再看到这个例外。


作为一种变通方法,在早期的熊猫,你可以使用apply

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 

,您可以在DF

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

很酷,谢谢 - 我想我不明白apply()和transform()之间的区别。改变某种程度上更严格? – patricksurry 2013-05-01 10:58:51

+0

@patricksurry我在想,如果它是一个错误,它肯定看起来应该适合变换类别... – 2013-05-01 11:34:30

+2

@patricksurry变换期望一个结果到组中的所有东西,而apply应用期望每行的值在群组。虽然这两个组的行为(子DataFrames),所以它有点混乱。 – 2013-10-23 20:51:15