Pandas groupby.agg() 函数
groupby.agg() 是 Pandas 中功能最强大的聚合函数之一,它允许你对分组后的数据同时应用多个不同的聚合函数。
与 sum()、mean() 等单一聚合函数不同,agg() 可以一次性计算多个统计指标,比如同时计算每个分组的总和、平均值、最大值、最小值等。
在数据分析中,经常需要对数据同时进行多种统计分析,agg() 函数可以让这一过程变得简洁高效。
基本语法与参数
agg() 是 GroupBy 对象的成员函数,需要先使用 groupby() 分组后再调用。
语法格式
GroupBy.agg(func=None, axis=0, *args, engine=None, engine_kwargs=None, **kwargs)
参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| func | str、list、dict 或 callable | 聚合函数。可以是单个函数名、函数列表、对各列指定不同函数的字典。 | None |
| axis | int | 应用聚合的轴方向,0 表示按行(分组维度),1 表示按列。 | 0 |
| args | tuple | 传递给聚合函数的额外位置参数。 | () |
| engine | str | 指定计算引擎,可以是 'cython' 或 'numba'。None 表示由 Pandas 自动选择。 | None |
| engine_kwargs | dict | 传递给底层引擎的额外参数字典。 | None |
返回值
- 返回类型:
Series或DataFrame - 说明:返回分组聚合后的结果,结果结构取决于 func 参数和分组方式。
实例
让我们通过一系列从简单到复杂的例子,彻底掌握 groupby.agg() 的用法。
示例 1:使用内置聚合函数
最简单的方式是直接使用 Pandas 内置的聚合函数名称,如 'sum'、'mean'、'max'、'min'、'count' 等。
实例
import pandas as pd
# 创建销售数据 DataFrame
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100],
'数量': [10, 20, 15, 18, 22, 16, 12, 21]
}
df = pd.DataFrame(data)
print("原始销售数据:")
print(df)
print()
# 按"地区"分组,对"销售额"列同时应用多个聚合函数
# 使用字符串列表指定多个聚合函数
result = df.groupby('地区')['销售额'].agg(['sum', 'mean', 'max', 'min', 'count'])
print("每个地区销售额的汇总统计:")
print(result)
print()
# 同时对"销售额"和"数量"列进行聚合
result_all = df.groupby('地区').agg({
'销售额': ['sum', 'mean'],
'数量': ['sum', 'mean']
})
print("各地区销售和数量的综合统计:")
print(result_all)
# 创建销售数据 DataFrame
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100],
'数量': [10, 20, 15, 18, 22, 16, 12, 21]
}
df = pd.DataFrame(data)
print("原始销售数据:")
print(df)
print()
# 按"地区"分组,对"销售额"列同时应用多个聚合函数
# 使用字符串列表指定多个聚合函数
result = df.groupby('地区')['销售额'].agg(['sum', 'mean', 'max', 'min', 'count'])
print("每个地区销售额的汇总统计:")
print(result)
print()
# 同时对"销售额"和"数量"列进行聚合
result_all = df.groupby('地区').agg({
'销售额': ['sum', 'mean'],
'数量': ['sum', 'mean']
})
print("各地区销售和数量的综合统计:")
print(result_all)
运行结果:
原始销售数据:
地区 产品 销售额 数量
0 华北 A 1000 10
1 华东 B 2000 20
2 华南 C 1500 15
3 华北 B 1800 18
4 华东 A 2200 22
5 华南 C 1600 16
6 华北 A 1200 12
7 华东 B 2100 21
每个地区销售额的汇总统计:
sum mean max min count
地区
华东 7100 1775.0 2200 2000 4
华南 3100 1550.0 1600 1500 2
华北 4000 1333.333333 1800 1000 3
各地区销售和数量的综合统计:
销售额 数量
sum mean sum mean
地区
华东 7100 1775.0 83 20.75
华南 3100 1550.0 31 15.50
华北 4000 1333.333333 40 13.33
代码解析:
['sum', 'mean', 'max', 'min', 'count']使用列表可以同时指定多个聚合函数。- 返回的结果是一个 DataFrame,列名由函数名和原始列名组成(多层列索引)。
- 使用字典可以为不同的列指定不同的聚合函数。
示例 2:使用自定义聚合函数
除了内置函数,agg() 还支持自定义函数,这大大扩展了其灵活性。
实例
import pandas as pd
import numpy as np
# 创建学生成绩数据
data = {
'班级': ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'A'],
'姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八', '吴九', '郑十'],
'语文': [85, 92, 78, 88, 95, 82, 90, 87],
'数学': [90, 85, 92, 78, 88, 91, 85, 89]
}
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 定义自定义聚合函数
def range_func(x):
"""计算最大值与最小值的差(极差)"""
return x.max() - x.min()
def coefficient_of_variation(x):
"""计算变异系数(标准差/平均值)"""
return x.std() / x.mean() * 100
# 使用自定义函数进行聚合
# 可以使用函数名(字符串)或直接传入函数对象
result = df.groupby('班级').agg({
'语文': ['sum', 'mean', range_func], # 对语文:总和、平均值、极差
'数学': ['sum', 'mean', coefficient_of_variation] # 对数学:总和、平均值、变异系数
})
print("各班级的自定义统计:")
print(result)
print()
# 也可以直接在列表中使用自定义函数
result2 = df.groupby('班级')['数学'].agg(['mean', range_func, 'std'])
print("各班级数学成绩的统计(包含自定义极差和标准差):")
print(result2)
import numpy as np
# 创建学生成绩数据
data = {
'班级': ['A', 'A', 'A', 'B', 'B', 'B', 'B', 'A'],
'姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八', '吴九', '郑十'],
'语文': [85, 92, 78, 88, 95, 82, 90, 87],
'数学': [90, 85, 92, 78, 88, 91, 85, 89]
}
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 定义自定义聚合函数
def range_func(x):
"""计算最大值与最小值的差(极差)"""
return x.max() - x.min()
def coefficient_of_variation(x):
"""计算变异系数(标准差/平均值)"""
return x.std() / x.mean() * 100
# 使用自定义函数进行聚合
# 可以使用函数名(字符串)或直接传入函数对象
result = df.groupby('班级').agg({
'语文': ['sum', 'mean', range_func], # 对语文:总和、平均值、极差
'数学': ['sum', 'mean', coefficient_of_variation] # 对数学:总和、平均值、变异系数
})
print("各班级的自定义统计:")
print(result)
print()
# 也可以直接在列表中使用自定义函数
result2 = df.groupby('班级')['数学'].agg(['mean', range_func, 'std'])
print("各班级数学成绩的统计(包含自定义极差和标准差):")
print(result2)
运行结果:
学生成绩数据:
班级 姓名 语文 数学
0 A 张三 85 90
1 A 李四 92 85
2 A 王五 78 92
3 B 赵六 88 78
4 B 孙七 95 88
5 B 周八 82 91
6 B 吴九 90 85
7 A 郑十 87 89
各班级的自定义统计:
语文 数学
sum mean range_func sum mean coefficient_of_variation
班级
A 342 85.5 14.0 425 88.25 5.019099
B 355 88.75 12.0 342 85.5 7.030
各班级数学成绩的统计(包含自定义极差和统计):
班级
A 88.25 5.0 2.692582
B 85.50 13.0 6.0
代码解析:
- 自定义函数接收一个 Series 作为参数,返回一个标量值。
- 函数名可以以字符串形式传入(如
'sum'),也可以直接传入函数对象。 - 使用自定义函数可以实现任意复杂的聚合逻辑。
示例 3:使用字符串别名和 lambda 函数
agg() 支持多种函数指定方式,包括 lambda 表达式和内置字符串别名。
实例
import pandas as pd
# 创建员工工资数据
data = {
'部门': ['销售', '销售', '技术', '技术', '行政', '行政', '销售', '技术'],
'岗位': ['专员', '经理', '专员', '经理', '专员', '经理', '专员', '经理'],
'工资': [5000, 8000, 7000, 12000, 4500, 9000, 5500, 11000],
'工龄': [2, 5, 3, 8, 1, 6, 2, 7]
}
df = pd.DataFrame(data)
print("员工工资数据:")
print(df)
print()
# 使用 lambda 函数进行灵活的自定义计算
# 计算每个部门工资的中位数与平均值的差异
result = df.groupby('部门').agg({
'工资': [
('平均工资', 'mean'), # 给聚合结果起别名
('最高工资', 'max'),
('最低工资', 'min'),
('工资极差', lambda x: x.max() - x.min())
],
'工龄': [
('平均工龄', 'mean'),
('最高工龄', 'max'),
('最低工龄', 'min')
]
})
print("各部门工资和工龄的综合统计:")
print(result)
print()
# 使用 agg 的简写形式
result2 = df.groupby('部门')['工资'].agg(
平均='mean',
总和='sum',
人数='count'
)
print("使用命名参数形式的聚合结果:")
print(result2)
# 创建员工工资数据
data = {
'部门': ['销售', '销售', '技术', '技术', '行政', '行政', '销售', '技术'],
'岗位': ['专员', '经理', '专员', '经理', '专员', '经理', '专员', '经理'],
'工资': [5000, 8000, 7000, 12000, 4500, 9000, 5500, 11000],
'工龄': [2, 5, 3, 8, 1, 6, 2, 7]
}
df = pd.DataFrame(data)
print("员工工资数据:")
print(df)
print()
# 使用 lambda 函数进行灵活的自定义计算
# 计算每个部门工资的中位数与平均值的差异
result = df.groupby('部门').agg({
'工资': [
('平均工资', 'mean'), # 给聚合结果起别名
('最高工资', 'max'),
('最低工资', 'min'),
('工资极差', lambda x: x.max() - x.min())
],
'工龄': [
('平均工龄', 'mean'),
('最高工龄', 'max'),
('最低工龄', 'min')
]
})
print("各部门工资和工龄的综合统计:")
print(result)
print()
# 使用 agg 的简写形式
result2 = df.groupby('部门')['工资'].agg(
平均='mean',
总和='sum',
人数='count'
)
print("使用命名参数形式的聚合结果:")
print(result2)
运行结果:
员工工资数据:
部门 岗位 工资 工龄
0 销售 专员 5000 2
1 销售 经理 8000 5
2 技术 专员 7000 3
3 技术 经理 12000 8
4 行政 专员 4500 1
5 行政 经理 9000 6
6 销售 专员 5500 2
7 技术 经理 11000 7
各部门工资和工龄的综合统计:
工资 工龄
平均工资 最高工资 最低工资 工资极差 平均工龄 最高工龄 最低工龄
部门
技术 10000.0 12000 7000 5000 6.0 8 3
行政 6750.0 9000 4500 4500 3.5 6 1
销售 6166.666667 8000 5000 3000 3.0 5 1
使用命名参数形式的聚合结果:
平均 总和 人数
部门
技术 10000.0 30000 3
行政 6750.0 13500 2
销售 6166.666667 18500 3
代码解析:
- 使用元组
('别名', '函数名')可以给聚合结果列指定自定义名称。 - Lambda 表达式可以直接在
agg()中使用,实现简单的自定义逻辑。 - 命名参数形式(关键字参数)可以更直观地为结果列指定名称。
示例 4:按多列分组并使用 agg
agg() 也可以与多列分组配合使用,处理更复杂的数据分析需求。
实例
import pandas as pd
# 创建销售数据
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东', '华南'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B', 'C'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100, 1700],
'利润': [200, 400, 300, 360, 440, 320, 240, 420, 340]
}
df = pd.DataFrame(data)
print("销售数据:")
print(df)
print()
# 按地区和产品分组,对销售额和利润进行多种聚合
result = df.groupby(['地区', '产品']).agg({
'销售额': ['sum', 'mean', 'count'],
'利润': ['sum', 'mean']
})
print("按地区和产品分组后的聚合结果:")
print(result)
print()
# 使用 reset_index 转换为普通 DataFrame 格式
result_flat = df.groupby(['地区', '产品'], as_index=False).agg({
'销售额': ['sum', 'mean'],
'利润': ['sum', 'mean']
})
# 展平多层列索引
result_flat.columns = ['_'.join(col).strip('_') for col in result_flat.columns.values]
print("展平后的结果:")
print(result_flat)
# 创建销售数据
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东', '华南'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B', 'C'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100, 1700],
'利润': [200, 400, 300, 360, 440, 320, 240, 420, 340]
}
df = pd.DataFrame(data)
print("销售数据:")
print(df)
print()
# 按地区和产品分组,对销售额和利润进行多种聚合
result = df.groupby(['地区', '产品']).agg({
'销售额': ['sum', 'mean', 'count'],
'利润': ['sum', 'mean']
})
print("按地区和产品分组后的聚合结果:")
print(result)
print()
# 使用 reset_index 转换为普通 DataFrame 格式
result_flat = df.groupby(['地区', '产品'], as_index=False).agg({
'销售额': ['sum', 'mean'],
'利润': ['sum', 'mean']
})
# 展平多层列索引
result_flat.columns = ['_'.join(col).strip('_') for col in result_flat.columns.values]
print("展平后的结果:")
print(result_flat)
运行结果:
销售数据:
地区 产品 销售额 利润
0 华北 A 1000 200
1 华东 B 2000 400
2 华南 C 1500 300
3 华北 B 1800 360
4 华东 A 2200 440
5 华南 C 1600 320
6 华北 A 1200 240
7 华东 B 2100 420
9 华南 C 1700 340
按地区和产品分组后的聚合结果:
销售额 利润
sum mean count sum mean
地区 产品
华东 A 2200 2200.0 1 440 440.0
B 4100 2050.0 2 4100 4100.0
华南 C 3100 1550.0 2 3100 1550.0
华北 A 2200 1100.0 2 440 220.0
B 1800 1800.0 1 360 360.0
展平后的结果:
地区 产品 销售额_sum 销售额_mean 利润_sum 利润_mean
0 华东 A 2200 2200.0 440 440.0
1 华东 B 4100 2050.0 820 410.0
2 华南 C 3100 1550.0 660 330.0
3 华北 A 2200 1100.0 440 220.0
4 华北 B 1800 1800.0 360 360.0
代码解析:
- 多列分组会产生多级索引(MultiIndex)。
- 使用
as_index=False可以将分组列保留为普通列。 - 通过
columns重新命名可以将多层列索引展平为单层。
提示:
agg()是分组聚合中最常用的函数之一,它不仅可以一次性计算多个统计指标,还支持自定义函数,灵活度非常高。建议在实际项目中熟练掌握它的各种用法。

Pandas 常用函数