pandas中的agg&transform方法
1 聚合函数 agg
1.1 介绍
agg
方法是pandas中用于数据集汇总的函数,它可以将聚合行为应用于一组函数(字符串、函数或名称),这些函数将被应用于每一行或列,并返回单个结果,以使汇总多个函数变得更加容易。
它主要用于列表等结构化数据汇总,例如:
• 根据某几列计算某几列的值
• 根据某几列聚合数据
• 根据某几列计算多个数据表的值
使用 pandas 中的 agg
方法可以实现多种数据汇总操作:
1、传入一个agg
函数,只需要一个聚合函数作为参数,默认地调用给定的聚合函数每一列:
import numpy as np
data.agg(np.mean)
2、传入一个字典,在字典中,columns作为键,对应的值则是函数,根据指定的列选择聚合函数:
import numpy as np
data.agg({'height': np.mean, 'weight': np.sum})
3、传入一个函数,可以传入自定义的函数:
def myfunc(x):
retrun x.max() - x.min()
data.agg(myfunc)
pandas的agg
函数也可以在grouby
中使用,以实现按分组聚合指定的统计列的结果。例如:
import numpy as np
data.groupby('Category').agg(np.mean)
此语句将使用Category分组,并用np.mean
方法聚合该分组下的所有统计列的结果,并返回一个分组结合的聚合结果DataFrame。
1.2 使用案例
首先模拟出一组学生成绩表数据:
import numpy as np
import pandas as pd
# 条件
cust_list = ['张三', '李四', '王五', '赵六']
item_list = ['苹果', '香蕉', '橘子', '南瓜']
price_list = [10, 5, 6, 8]
quant_list = [5, 3, 4, 7]
# 创建DataFrame
df = pd.DataFrame({'客户': np.random.choice(cust_list, size=20),
'商品': np.random.choice(item_list, size=20),
'价格': np.random.choice(price_list, size=20),
'数量': np.random.choice(quant_list, size=20),
})
# 查看数据
df
客户 | 商品 | 价格 | 数量 | |
---|---|---|---|---|
0 | 张三 | 苹果 | 10 | 3 |
1 | 赵六 | 苹果 | 8 | 3 |
2 | 王五 | 南瓜 | 8 | 5 |
3 | 赵六 | 橘子 | 5 | 5 |
4 | 张三 | 橘子 | 8 | 4 |
5 | 赵六 | 橘子 | 5 | 7 |
6 | 张三 | 苹果 | 8 | 4 |
7 | 赵六 | 橘子 | 10 | 5 |
8 | 赵六 | 苹果 | 5 | 3 |
9 | 赵六 | 橘子 | 5 | 5 |
10 | 李四 | 香蕉 | 5 | 7 |
11 | 赵六 | 香蕉 | 10 | 3 |
12 | 李四 | 苹果 | 5 | 7 |
13 | 张三 | 香蕉 | 6 | 4 |
14 | 王五 | 苹果 | 5 | 5 |
15 | 赵六 | 橘子 | 10 | 3 |
16 | 李四 | 香蕉 | 10 | 7 |
17 | 李四 | 橘子 | 10 | 3 |
18 | 李四 | 橘子 | 10 | 5 |
19 | 王五 | 橘子 | 5 | 4 |
统计每个客户购买的商品总数量:
df.groupby('客户')[['数量']].agg(np.sum)
数量 | |
---|---|
客户 | |
张三 | 15 |
李四 | 29 |
王五 | 14 |
赵六 | 34 |
df.groupby('客户').agg(总数=pd.NamedAgg(column='数量', aggfunc=np.sum))
总数 | |
---|---|
客户 | |
张三 | 15 |
李四 | 29 |
王五 | 14 |
赵六 | 34 |
统计每个客户购买的每种商品数量:
def myfunc(x):
return np.sum(x)
df.groupby(['客户', '商品'])[['数量']].agg(myfunc)
数量 | ||
---|---|---|
客户 | 商品 | |
张三 | 橘子 | 4 |
苹果 | 7 | |
香蕉 | 4 | |
李四 | 橘子 | 8 |
苹果 | 7 | |
香蕉 | 14 | |
王五 | 南瓜 | 5 |
橘子 | 4 | |
苹果 | 5 | |
赵六 | 橘子 | 25 |
苹果 | 6 | |
香蕉 | 3 |
统计客户购买的商品个数以及购买商品的最大最小总计:
df.groupby('客户').agg({'数量': [np.max, np.min, np.sum], '商品': np.size})
数量 | 商品 | |||
---|---|---|---|---|
amax | amin | sum | size | |
客户 | ||||
张三 | 4 | 3 | 15 | 4 |
李四 | 7 | 3 | 29 | 5 |
王五 | 5 | 4 | 14 | 3 |
赵六 | 7 | 3 | 34 | 8 |
2 transform方法
2.1 介绍
pandas的transform方法是分组变换的一个重要功能,作用是对每个组进行某种变换,以计算每个分组的统计值或利用转换函数来改变每组中的值。
可以通过transform方法来实现一些数据相关的功能,例如:分组标准化(Z-score),归一化(Min-Max scale),缺失值处理(均值填充或其他策略)等。
result = df.groupby('group').transform(lambda x: (x - x.mean()) / x.std())
transform
方法可以对每一个group进行一些变换,然后返回一个新的DataFrame,它包含每一个group的变换后的新值。
转换后的数据框仍然与原来分组前的数据框位置和行数一致。
2.2 使用案例
先模拟生成一组采购订单数据信息:
import pandas as pd
import numpy as np
import string
import random
# 随机生成5个订单号
order_no_list = [''.join(random.choices(string.ascii_uppercase + string.digits, k=8)) for i in range(5)]
# 生成采购数量
order_num_list = np.random.randint(1,11, size= 20)
# 构造字典
df = {
'采购订单号': np.random.choice(order_no_list, size=20),
'采购数量': np.random.choice(order_num_list, size=20)
}
# 传入字典构造DataFrame
df = pd.DataFrame(df)
df
采购订单号 | 采购数量 | |
---|---|---|
0 | DLPERDUD | 5 |
1 | 4UNV1UFJ | 6 |
2 | QR2ASQTX | 6 |
3 | JZLAS8AY | 1 |
4 | 6TBOCEQT | 6 |
5 | DLPERDUD | 6 |
6 | 4UNV1UFJ | 8 |
7 | 6TBOCEQT | 1 |
8 | QR2ASQTX | 2 |
9 | JZLAS8AY | 8 |
10 | JZLAS8AY | 1 |
11 | 4UNV1UFJ | 7 |
12 | 6TBOCEQT | 6 |
13 | 6TBOCEQT | 9 |
14 | QR2ASQTX | 2 |
15 | 4UNV1UFJ | 4 |
16 | 6TBOCEQT | 3 |
17 | QR2ASQTX | 3 |
18 | QR2ASQTX | 9 |
19 | DLPERDUD | 7 |
按照采购订单号分组统计采购数量的合计值:
df['总数'] = df.groupby('采购订单号')['采购数量'].transform(np.sum)
df
采购订单号 | 采购数量 | 总数 | |
---|---|---|---|
0 | DLPERDUD | 5 | 18 |
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
3 | JZLAS8AY | 1 | 10 |
4 | 6TBOCEQT | 6 | 25 |
5 | DLPERDUD | 6 | 18 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
9 | JZLAS8AY | 8 | 10 |
10 | JZLAS8AY | 1 | 10 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |
19 | DLPERDUD | 7 | 18 |
筛选出采购订单号对应的采购总数大于20的数据:
# 筛选
df[df.groupby('采购订单号')['采购数量'].transform(np.sum) > 20]
采购订单号 | 采购数量 | 总数 | |
---|---|---|---|
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
4 | 6TBOCEQT | 6 | 25 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |
# 上面的筛选也可以这么写
df[df.groupby('采购订单号')['采购数量'].transform(lambda x: x.sum() > 20)]
采购订单号 | 采购数量 | 总数 | |
---|---|---|---|
1 | 4UNV1UFJ | 6 | 25 |
2 | QR2ASQTX | 6 | 22 |
4 | 6TBOCEQT | 6 | 25 |
6 | 4UNV1UFJ | 8 | 25 |
7 | 6TBOCEQT | 1 | 25 |
8 | QR2ASQTX | 2 | 22 |
11 | 4UNV1UFJ | 7 | 25 |
12 | 6TBOCEQT | 6 | 25 |
13 | 6TBOCEQT | 9 | 25 |
14 | QR2ASQTX | 2 | 22 |
15 | 4UNV1UFJ | 4 | 25 |
16 | 6TBOCEQT | 3 | 25 |
17 | QR2ASQTX | 3 | 22 |
18 | QR2ASQTX | 9 | 22 |