Pandas:分组级的运算和转换--transform和apply

时间:2021-07-15 18:34:00
import numpy as np
import pandas as pd
from pandas import Series,DataFrame

一、介绍

聚集函数只是将一组值转换为一个标量值,其实还可以将更多类型的函数应用到分组上,下面的transform和apply就提供这样的功能。

二、transform

transform中传入的函数只能返回两种结果,可以广播的标量值或者与分组大小相同的结果数组。

df = DataFrame({'类别':['水果','水果','水果','蔬菜','蔬菜','肉类','肉类'],
                '产地':['美国','中国','中国','中国','新西兰','新西兰','美国'],
                '水果':['苹果','梨','草莓','番茄','黄瓜','羊肉','牛肉'],
               '数量':[5,5,9,3,2,10,8],
               '价格':[5,5,10,3,3,13,20]})
print(df)
    产地  价格  数量  水果  类别
0   美国   5   5  苹果  水果
1   中国   5   5   梨  水果
2   中国  10   9  草莓  水果
3   中国   3   3  番茄  蔬菜
4  新西兰   3   2  黄瓜  蔬菜
5  新西兰  13  10  羊肉  肉类
6   美国  20   8  牛肉  肉类

1.对分组求均值,然后把这个均值赋值给整个组(可广播的标量值)

print(df.groupby('类别').transform(np.mean))
          价格        数量
0   6.666667  6.333333
1   6.666667  6.333333
2   6.666667  6.333333
3   3.000000  2.500000
4   3.000000  2.500000
5  16.500000  9.000000
6  16.500000  9.000000

2.使用transform实现去均值(返回与分组大小相同的结果数组)

demean = lambda arr:arr-arr.mean()
print(df.groupby('类别').transform(demean))
         价格        数量
0 -1.666667 -1.333333
1 -1.666667 -1.333333
2  3.333333  2.666667
3  0.000000  0.500000
4  0.000000 -0.500000
5 -3.500000  1.000000
6  3.500000 -1.000000

三、apply

apply会将分组传递给函数,然后尝试将函数的返回结果组合起来。

def get_rows(df,n=1): # 返回分组的前n行数据
    return df.iloc[:n,:]
print(df.groupby('类别').apply(get_rows))
       产地  价格  数量  水果  类别
类别                       
水果 0   美国   5   5  苹果  水果
肉类 5  新西兰  13  10  羊肉  肉类
蔬菜 3   中国   3   3  番茄  蔬菜

为apply的函数传递参数

print(df.groupby('类别').apply(get_rows,n=2))
       产地  价格  数量  水果  类别
类别                       
水果 0   美国   5   5  苹果  水果
   1   中国   5   5   梨  水果
肉类 5  新西兰  13  10  羊肉  肉类
   6   美国  20   8  牛肉  肉类
蔬菜 3   中国   3   3  番茄  蔬菜
   4  新西兰   3   2  黄瓜  蔬菜