【问题标题】:Calling Functions with Multiple Arguments when using Groupby使用 Groupby 时调用具有多个参数的函数
【发布时间】:2013-11-14 16:23:42
【问题描述】:

如果在 pandas 中编写要与 groupby.apply 或 groupby.transform 一起使用的函数,如果函数有多个参数,那么在将函数作为 groupby 的一部分调用时,参数后面会使用逗号而不是括号。一个例子是:

def Transfunc(df, arg1, arg2, arg2):
     return something

GroupedData.transform(Transfunc, arg1, arg2, arg3)

df 参数作为第一个参数自动传递。

但是,使用函数对数据进行分组时,似乎无法使用相同的语法。举个例子:

people = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
people.ix[2:3, ['b', 'c']] = NA

def MeanPosition(Ind, df, Column):
    if df[Column][Ind] >= np.mean(df[Column]):
        return 'Greater Group'
    else:
        return 'Lesser Group'
# This function compares each data point in column 'a' to the mean of column 'a' and return a group name based on whether it is greater than or less than the mean

people.groupby(lambda x: MeanPosition(x, people, 'a')).mean()

上面的工作很好,但我不明白为什么我必须将函数包装在 lambda 中。根据与 transform 和 apply 一起使用的语法,在我看来,以下内容应该可以正常工作:

people.groupby(MeanPosition, people, 'a').mean()

谁能告诉我为什么,或者我如何在不将其包装在 lambda 中的情况下调用该函数?

谢谢

编辑:我认为不可能通过将函数作为键传递而不将该函数包装在 lambda 中来对数据进行分组。一种可能的解决方法是传递一个由函数创建的数组,而不是将函数作为键传递。这将通过以下方式起作用:

def MeanPositionList(df, Column):
    return ['Greater Group' if df[Column][row] >= np.mean(df[Column]) else 'Lesser Group' for row in df.index]

Grouped = people.groupby(np.array(MeanPositionList(people, 'a')))
Grouped.mean()

但是当然最好把中间人函数全部去掉,然后简单地使用一个具有列表理解的数组....

【问题讨论】:

  • 我认为这是设计决策,您可以查看来源并查看是否可能(据我所知,它不是)以及将来是否可以将**kwarg 添加到 groupby 跨度>
  • 令人沮丧!我的意思是把它包装在一个 lambda 中很容易,但很难解释为什么会这样......

标签: python lambda pandas


【解决方案1】:

将参数传递给apply 恰好可以工作,因为apply 将所有参数传递给目标函数。

但是,groupby 接受多个参数,请参阅here,因此无法区分参数;传递一个 lambda / 命名函数更明确,也是可行的方法。

这是我认为你想做的事情(稍作修改,因为你的示例中有所有不同的组)

In [22]: def f(x):
   ....:     result = Series('Greater',index=x.index)
   ....:     result[x<x.mean()] = 'Lesser'
   ....:     return result
   ....: 

In [25]: df = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe', 'Joe', 'Wes', 'Wes', 'Travis'])

In [26]: df
Out[26]: 
               a         b         c         d         e
Joe    -0.293926  1.006531  0.289749 -0.186993 -0.009843
Joe    -0.228721 -0.071503  0.293486  1.126972 -0.808444
Wes     0.022887 -1.813960  1.195457  0.216040  0.287745
Wes    -1.520738 -0.303487  0.484829  1.644879  1.253210
Travis -0.061281 -0.517140  0.504645 -1.844633  0.683103

In [27]: df.groupby(df.index.values).transform(f)
Out[27]: 
              a        b        c        d        e
Joe      Lesser  Greater   Lesser   Lesser  Greater
Joe     Greater   Lesser  Greater  Greater   Lesser
Travis  Greater  Greater  Greater  Greater  Greater
Wes     Greater   Lesser  Greater   Lesser   Lesser
Wes      Lesser  Greater   Lesser  Greater  Greater

【讨论】:

  • 谢谢杰夫。这就是我的假设,但我想知道的是,我怎样才能传递上面有多个参数但没有 lambda 表示法的命名函数。编写 people.groupby(MeanPosition(people, 'a')) 会生成一个错误,指出传递的参数不足。如何使用 lambda 表示法传递 Ind 参数?还是不可能?
  • 我编辑了答案。 grouper 函数在索引标签上调用,因此它只接受 1 个参数,理论上您可以使用偏函数。但是,我相信以上无论如何都可以解决您的问题。
  • 谢谢,实际上这并不是我想要的。我已经编辑了我的问题。我不认为我想做的事情可以实现(即调用组函数而不将其包装在 lambda 中)。一种解决方法是将密钥传递给组操作,该操作本身就是由函数创建的数组。
猜你喜欢
  • 2020-12-07
  • 2022-09-23
  • 2013-06-13
  • 2011-11-21
  • 1970-01-01
  • 2021-01-11
  • 2013-10-17
  • 1970-01-01
  • 2020-01-27
相关资源
最近更新 更多