【问题标题】:Pass Multiple Columns to groupby.transform将多列传递给 groupby.transform
【发布时间】:2013-10-27 14:21:16
【问题描述】:

我了解,当您使用 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']

现在我可以很容易地贬低数据等,但我似乎无法正确做的是使用多个列值作为函数的参数来转换组内的数据。例如,如果我想为每个观察添加一个取值 a.mean() - b.mean() * c 的列 'f',如何使用 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。

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

帮助表示赞赏。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    你可以使用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) 当用 apply 调用函数 f 时,传递了什么?每组数据是按顺序排列的吗?我认为它必须是。 2) 如何使用多列调用函数,因此 people2 = Grouped.apply(f('a', 'b', 'c'))?显然,必须更改功能,但在您的示例中,该功能不是很抽象。我想写 def f(df, col1, col2, col3) - 这样它就可以在函数内部引用的列之外使用。
    • 是的,因为在您的示例中,函数只能用于返回根据 col a b 和 c 的输入修改的 f 列。如何概括这一点?
    • 是的,我需要使用 kwargs 进行修改,但这似乎是正确的。我想概括一下,以便我可以使用列 d、e、f 等,所以我会在调用函数时输入这些作为参数。我根据您的回答完整地提供了答案。你觉得有道理吗?感谢您的帮助,这一直困扰我一段时间。
    • +1,我认为答案的主要部分是使用apply而不是transform
    • 这样说是否正确,调用 transform 仅将命名列或 DF 中的每一列单独传递给函数,并且不能传递多个列,而 apply 传递整个数据框然后列值可以在函数中使用吗?我认为那是我弄错的地方......
    【解决方案2】:

    这是基于 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 传递给函数,然后列可以作为参数调用。

    【讨论】:

    • 在结果 DataFrame people2 中是否有列“f”?
    • 不,你完全正确,我没有提到我在分组之前创建了一个空列 f。我现在已经在代码中添加了这个。
    • 好的,我认为在@HYRY 回答中应用在这里更合适?
    猜你喜欢
    • 1970-01-01
    • 2014-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多