如何将*多个*函数应用于pandas groupby apply?

Qas*_*wed 5 aggregate function apply pandas pandas-groupby

我有一个数据框,应将其分组,然后在每个组上应用几个函数。通常,我会这样做groupby().agg()(参见将多个函数应用于多个 groupby 列),但我感兴趣的函数不需要一列作为输入,而是需要多列。

我了解到,当我有一个具有多列作为输入的函数时,我需要apply(参见使用多列的 Pandas DataFrame 聚合函数)。 但是,当我有多个具有多个列作为输入的函数时,我需要什么?

import pandas as pd
df = pd.DataFrame({'x':[2, 3, -10, -10], 'y':[10, 13, 20, 30], 'id':['a', 'a', 'b', 'b']})

def mindist(data): #of course these functions are more complicated in reality
     return min(data['y'] - data['x'])
def maxdist(data):
    return max(data['y'] - data['x'])
Run Code Online (Sandbox Code Playgroud)

我期待类似的东西df.groupby('id').apply([mindist, maxdist])

    min   max
id      
 a    8    10
 b   30    40
Run Code Online (Sandbox Code Playgroud)

(通过实现pd.DataFrame({'mindist':df.groupby('id').apply(mindist),'maxdist':df.groupby('id').apply(maxdist)}- 如果我有许多函数要应用于分组数据框,这显然不是很方便)。最初我以为这个OP有同样的问题,但他似乎对 很满意aggregate,这意味着他的函数只接受一列作为输入。

Mar*_*ang 10

groupby对于这个具体问题,差异之后怎么样?

(df['x']-df['y']).groupby(df['id']).agg(['min','max'])
Run Code Online (Sandbox Code Playgroud)

更一般地说,你可能可以做类似的事情

df.groupby('id').apply(lambda x:pd.Series({'min':mindist(x),'max':maxdist(x)}))
Run Code Online (Sandbox Code Playgroud)


rpa*_*nai 6

IIUC 您想在同一组中使用多个函数。在这种情况下,您应该返回一个pd.Series. 在下面的玩具示例中我想要

  1. 对列求和AB然后计算平均值
  2. 对列求和CD然后计算标准差
import pandas as pd
df = pd.util.testing.makeDataFrame().head(10)
df["key"] = ["key1"] * 5 + ["key2"] * 5

def fun(x):
    m = (x["A"]+x["B"]).mean()
    s = (x["C"]+x["D"]).std()
    return pd.Series({"meanAB":m, "stdCD":s})

df.groupby("key").apply(fun)

Run Code Online (Sandbox Code Playgroud)

更新 在你的情况下变成了

import pandas as pd

df = pd.DataFrame({'x':[2, 3, -10, -10],
                   'y':[10, 13, 20, 30],
                   'id':['a', 'a', 'b', 'b']})

def mindist(data): #of course these functions are more complicated in reality
     return min(data['y'] - data['x'])

def maxdist(data):
    return max(data['y'] - data['x'])

def fun(data):
    return pd.Series({"maxdist":maxdist(data),
                      "mindist":mindist(data)})

df.groupby('id').apply(fun)
Run Code Online (Sandbox Code Playgroud)