Pandas:df.groupby(x, y).apply() 跨多个列参数错误

Posted

技术标签:

【中文标题】Pandas:df.groupby(x, y).apply() 跨多个列参数错误【英文标题】:Pandas: df.groupby(x, y).apply() across multiple columns parameter error 【发布时间】:2013-08-01 04:26:21 【问题描述】:

基本问题:

我有几个“过去”和“现在”变量,我想对它们执行简单的“row-wise”百分比变化。例如:((exports_now - exports_past)/exports_past))

这两个问题实现了这一点,但是当我尝试类似的方法时,我收到一个错误,即我的函数 deltas 获得了一个未知参数 axis

How to apply a function to two columns of Pandas dataframe Pandas: How to use apply function to multiple columns

数据示例:

exports_ past    exports_ now    imports_ past    imports_ now    ect.(6 other pairs)
   .23               .45             .43             .22              1.23
   .13               .21             .47             .32               .23
    0                 0              .41             .42               .93
   .23               .66             .43             .22               .21
    0                .12             .47             .21              1.23

按照第一个问题的答案,

我的解决方案是使用这样的函数:

def deltas(row):
    '''
    simple pct change
    '''
    if int(row[0]) == 0 and int(row[1]) == 0:
        return 0
    elif int(row[0]) == 0:
        return np.nan
    else:
        return ((row[1] - row[0])/row[0])

并像这样应用函数:

df['exports_delta'] = df.groupby(['exports_past', 'exports_now']).apply(deltas, axis=1)

这会产生这个错误:TypeError: deltas() got an unexpected keyword argument 'axis' 关于如何解决轴参数错误的任何想法?或者更优雅的计算 pct 变化的方法?我的问题的关键是我需要能够在几个不同的列对中应用这个函数,所以像第二个问题中的答案那样硬编码列名是不可取的。谢谢!

【问题讨论】:

【参考方案1】:

考虑使用pct_change Series/DataFrame 方法来执行此操作。

df.pct_change()

混淆源于两个不同(但名称相同)apply 函数,一个在 Series/DataFrame 上,一个在 groupby 上。

In [11]: df
Out[11]:
   0  1  2
0  1  1  1
1  2  2  2

DataFrame apply 方法接受一个轴参数:

In [12]: df.apply(lambda x: x[0] + x[1], axis=0)
Out[12]:
0    3
1    3
2    3
dtype: int64

In [13]: df.apply(lambda x: x[0] + x[1], axis=1)
Out[13]:
0    2
1    4
dtype: int64

groupby apply 没有,kwarg 被传递给函数:

In [14]: g.apply(lambda x: x[0] + x[1])
Out[14]:
0    2
1    4
dtype: int64

In [15]: g.apply(lambda x: x[0] + x[1], axis=1)
TypeError: <lambda>() got an unexpected keyword argument 'axis'

注意:groupby 确实有一个轴参数,所以如果你真的想的话,你可以在那里使用它:

In [16]: g1 = df.groupby(0, axis=1)

In [17]: g1.apply(lambda x: x.iloc[0, 0] + x.iloc[1, 0])
Out[17]:
0
1    3
2    3
dtype: int64

【讨论】:

感谢您的回答安迪。如果我坚持使用 groupby 应用并删除轴参数,我会收到一个关键错误 KeyError: u'no item named 0' 以访问 row[0] 等元素。有没有办法使用 groupby apply 并且仍然使用一种表示法,可以轻松地应用于几个不同命名的列对? 我想到了df.pct_change() 函数,但我相信它只适用于单个列。 IE。 df.pct_change(self, periods=1, fill_method='pad', limit=None, freq=None, **kwd)。我没有检查源代码,但我相信它通过类似于.shift() 方法的方式来完成它。如果这是真的,我不确定它是否可以应用于多个列。 @agconti 已更新,您可以使用axis=1 的groupby,您可以将pct_change 应用于整个数据框。或者,也许您想使用应用 (lambda x: x.pct_change()) 为每个组执行此操作。 我认为我的帖子中没有 100% 清楚。 (我更新了它)。我希望不通过在exports_past 和现在的exports 中移动期间而是通过使用这些值来进行pct_change() 计算。 IE。 ((exports_now - exports_past)/exports_past). 将axis=1 传递给groupby 会导致ValueError: Wrong number of items passed 1, indices imply 0 像这样使用:df['xx_delta'] = df.groupby(['xx_past', 'xx_now'], axis=1).apply(deltas)

以上是关于Pandas:df.groupby(x, y).apply() 跨多个列参数错误的主要内容,如果未能解决你的问题,请参考以下文章

Pandas - Groupby 多索引级别,获取可能的组合,然后转换数据

Python 重命名 Pandas DataFrame 列

Python Pandas groupby 应用 lambda 参数

python – Pandas使用groupby中的count来创建新列

python.pandas groupby根据最小值更改某列数据

Pandas 的 [df.groupby(...)['col_name'].shift(1)] 的 SQL 等效项