将多个列传递给groupby.transform

时间:2013-10-27 14:21:16

标签: python pandas

据我所知,当您使用DataFrame列调用groupby.transform时,该列将传递给转换数据的函数。但我无法理解的是如何将多列传递给函数。

people = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
key = ['one', 'two', 'one', 'two', 'one']

现在我可以很容易地贬低那些数据等,但我似乎无法正常做的是使用多个列值作为函数的参数来转换组内的数据。例如,如果我想添加一个列'f',它为每个观察值取a.mean() - b.mean()* c,那么如何使用transform方法获得它。

我尝试了以下

的变体
people['f'] = float(NA)
Grouped = people.groupby(key)
def TransFunc(col1, col2, col3):
    return col1.mean() - col2.mean() * col3
Grouped.f.transform(TransFunc(Grouped['a'], Grouped['b'], Grouped['c']))

但这显然是错误的。我还试图将函数包装在lamba中,但也不能完成这项工作。

我能够通过以下方式遍历组来实现结果:

for group in Grouped:
    Amean = np.mean(list(group[1].a))
    Bmean = np.mean(list(group[1].b))
    CList = list(group[1].c)
    IList = list(group[1].index)

    for y in xrange(len(CList)):
        people['f'][IList[y]] = (Amean - Bmean) * CList[y]

但这似乎不是一个令人满意的解决方案,特别是如果索引是非唯一的。我也知道使用groupby.transform这一定是可行的。

概括问题:如何编写函数来转换具有涉及使用多列值的参数的数据?

帮助表示赞赏。

2 个答案:

答案 0 :(得分:3)

您可以使用apply()方法:

import numpy as np
import pandas as pl
np.random.seed(0)

people2 = pd.DataFrame(np.random.randn(5, 5), 
                      columns=['a', 'b', 'c', 'd', 'e'], 
                      index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
key = ['one', 'two', 'one', 'two', 'one']

Grouped = people2.groupby(key)

def f(df):
    df["f"] = (df.a.mean() - df.b.mean())*df.c
    return df

people2 = Grouped.apply(f)
print people2

如果你想要一些概括方法:

Grouped = people2.groupby(key)

def f(a, b, c, **kw):
    return (a.mean() - b.mean())*c

people2["f"] = Grouped.apply(lambda df:f(**df))
print people2

答案 1 :(得分:0)

这是基于HYRY(谢谢)提供的答案,他让我看到了如何实现这一目标。我的版本只是泛化函数并在调用函数时输入函数的参数。我认为虽然函数必须用lambda调用:

import pandas as pd
import numpy as np
people = DataFrame(np.random.randn(5, 5), columns=['a', 'b', 'c', 'd', 'e'], index=['Joe',         'Steve', 'Wes', 'Jim', 'Travis'])
key = ['one', 'two', 'one', 'two', 'one']
people['f'] = ""
Grouped = people.groupby(key)

def FUNC(df, col1, col2, col3, col4):
    df[col1] = (df[col2].mean() - df[col3].mean())*df[col4]
    return df

people2 = Grouped.transform(lambda x: FUNC(x, 'f', 'a', 'b', 'c'))

在我看来,这是我看到的最佳方式...基本上整个分组数据框作为x传递给函数,然后列可以作为参数调用。