可以以及如何将参数传递给聚合中使用的多个函数?

时间:2017-08-17 21:11:08

标签: python pandas

考虑数据框df

df = pd.DataFrame(dict(
    A=list('xxxyyy'),
    B=[np.nan, 1, 2, 3, 4, np.nan]
))

df

   A    B
0  x  NaN
1  x  1.0
2  x  2.0
3  y  3.0
4  y  4.0
5  y  NaN

我可以使用agg中的函数并传递像这样的参数

df.groupby('A').B.agg(pd.Series.head, n=1)

A
x    NaN
y    3.0
Name: B, dtype: float64

但是,我想使用pd.Series.headpd.Series.tail运行聚合。我想将论据n=1传递给他们两个。

我希望这个聚合看起来像下面的结果。重要的是要注意我已经可以产生这个结果。我的目标是弄清楚如何将参数传递给传递给agg的多个函数。

如果无法做到,解释为什么这是一个有效的答案。

     h    t
A          
x  NaN  2.0
y  3.0  NaN

添加奖励
如果你想出来......这将是一个比我this question更好的解决方案。我会鼓励任何回答这个问题的人也回答那个问题。

2 个答案:

答案 0 :(得分:3)

如果我理解正确the source code,则无法完成:

def aggregate(self, func_or_funcs, *args, **kwargs):
    _level = kwargs.pop('_level', None)
    if isinstance(func_or_funcs, compat.string_types):
        return getattr(self, func_or_funcs)(*args, **kwargs)  # NOTE: (*args, **kwargs) are passed to the function

    if hasattr(func_or_funcs, '__iter__'):
        ret = self._aggregate_multiple_funcs(func_or_funcs,    # NOTE: `*args, **kwargs` got lost ...
                                             (_level or 0) + 1)  
    ...

注意:如果func_or_funcs '__iter__'属性*args**kwargs将被忽略......

答案 1 :(得分:2)

您可以将字典中的lambdas传递给agg

>> df.groupby('A').B.agg({'h': lambda s: s.head(1), 't': lambda s: s.tail(1)})

但你可能不会在将来通过它

  

FutureWarning:不推荐在系列上使用dict进行聚合   并将在以后的版本中删除

我更喜欢重命名lambdas并阻止

  

SpecificationError:函数名必须唯一,找到多个   命名

>> h = lambda s: s.head(1)
>> h.__name__ = 'h'
>> t = lambda s: s.tail(1)
>> t.__name__ = 't'
>> df.groupby('A').B.agg([h, t])
>>
>>     h     t
>> A        
>> x   NaN   2.0
>> y   3.0   NaN

看起来5行太多,但线条很短!

将其他kwargs传递给agg函数的一种可能的解决方法是使用partial

>> from functools import partial
>> df.groupby('A').B.agg([partial(pd.Series.head, n=1),
>>                        partial(pd.Series.tail, n=1)])
>>
>>     head  tail
>> A        
>> x   NaN   2.0
>> y   3.0   NaN