Pandas groupby.mean() 函数
groupby.mean() 是 Pandas 中用于分组后计算平均值的聚合函数。它与 groupby.sum() 配合使用,先将数据按某个列的值进行分组,然后计算每个分组中数值列的算术平均值。
在数据分析中,计算平均值是非常常见的需求。比如计算每个部门的平均工资、每个地区的平均销售额、每个班级的平均成绩等。mean() 函数能够快速完成这些任务。
基本语法与参数
mean() 是 GroupBy 对象的成员函数,需要先使用 groupby() 分组后再调用。
语法格式
GroupBy.mean(numeric_only=False, engine=None, engine_kwargs=None)
参数说明
| 参数 | 类型 | 说明 | 默认值 |
|---|---|---|---|
| numeric_only | bool | 如果为 True,则只对数值列计算平均值;如果为 False,会尝试对所有列计算平均值。 | False |
| engine | str | 指定计算引擎,可以是 'cython' 或 'numba'。None 表示由 Pandas 自动选择。 | None |
| engine_kwargs | dict | 传递给底层引擎的额外参数字典。 | None |
返回值
- 返回类型:
Series或DataFrame - 说明:返回分组计算平均值后的结果。如果对单列使用,返回 Series;如果对多列使用,返回 DataFrame。
实例
让我们通过一系列从简单到复杂的例子,彻底掌握 groupby.mean() 的用法。
示例 1:基础用法 - 按单列分组计算平均值
最基本的用法是按照某一列的值进行分组,然后计算另一列的平均值。
实例
import pandas as pd
# 创建学生成绩数据 DataFrame
# 包含学生姓名、班级、语文、数学、英语成绩
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],
'英语': [88, 90, 85, 92, 87, 89, 91, 86]
}
# 创建 DataFrame
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 按"班级"分组,计算每个班级的平均成绩
avg_by_class = df.groupby('班级').mean(numeric_only=True)
print("每个班级的平均成绩:")
print(avg_by_class)
print()
# 也可以只针对某一列计算平均值
math_avg_by_class = df.groupby('班级')['数学'].mean()
print("每个班级的数学平均成绩:")
print(math_avg_by_class)
# 创建学生成绩数据 DataFrame
# 包含学生姓名、班级、语文、数学、英语成绩
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],
'英语': [88, 90, 85, 92, 87, 89, 91, 86]
}
# 创建 DataFrame
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 按"班级"分组,计算每个班级的平均成绩
avg_by_class = df.groupby('班级').mean(numeric_only=True)
print("每个班级的平均成绩:")
print(avg_by_class)
print()
# 也可以只针对某一列计算平均值
math_avg_by_class = df.groupby('班级')['数学'].mean()
print("每个班级的数学平均成绩:")
print(math_avg_by_class)
运行结果预期:
学生成绩数据:
姓名 班级 语文 数学 英语
0 张三 A 85 90 88
1 李四 A 92 85 90
2 王五 A 78 92 85
3 赵六 B 怎么办 78 92
4 孙七 B 95 88 87
5 周八 B 82 91 89
6 吴九 B 90 85 91
7 郑十 A 87 89 86
每个班级的平均成绩:
语文 数学 英语
班级
A 85.500000 89.000000 87.250000
B 88.750000 85.500000 89.750000
每个班级的数学平均成绩:
班级
A 89.0
B 85.5
dtype: float64
代码解析:
df.groupby('班级')按照"班级"列的值将学生分成 A、B 两组。.mean(numeric_only=True)对所有数值列(语文、数学、英语)计算平均值。- 返回的结果中,班级作为索引,各科目的平均值作为列数据。
示例 2:按多列分组计算平均值
可以同时按多个列进行分组,然后计算数值列的平均值。
实例
import pandas as pd
# 创建销售数据
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100],
'利润': [200, 400, 300, 360, 440, 320, 240, 420]
}
df = pd.DataFrame(data)
print("销售数据:")
print(df)
print()
# 按"地区"和"产品"分组,计算平均销售额和利润
avg_grouped = df.groupby(['地区', '产品'], as_index=False).mean(numeric_only=True)
print("按地区和产品分组后的平均销售额和利润:")
print(avg_grouped)
print()
# 保留多级索引形式
avg_indexed = df.groupby(['地区', '产品']).mean(numeric_only=True)
print("多级索引形式的结果:")
print(avg_indexed)
# 创建销售数据
data = {
'地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
'产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
'销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100],
'利润': [200, 400, 300, 360, 440, 320, 240, 420]
}
df = pd.DataFrame(data)
print("销售数据:")
print(df)
print()
# 按"地区"和"产品"分组,计算平均销售额和利润
avg_grouped = df.groupby(['地区', '产品'], as_index=False).mean(numeric_only=True)
print("按地区和产品分组后的平均销售额和利润:")
print(avg_grouped)
print()
# 保留多级索引形式
avg_indexed = df.groupby(['地区', '产品']).mean(numeric_only=True)
print("多级索引形式的结果:")
print(avg_indexed)
运行结果预期:
销售数据:
地区 产品 销售额 利润
0 华北 A 1000 200
1 华东 B 2000 reset_index
2 华南 C 1500 300
3 华北 B 1800 360
4 华东 A 保留 440
5 对齐 C 1600 320
6 华北 A 1200 240
7 华东 B 2100 420
按地区和产品分组后的平均销售额和利润:
地区 产品 销售额 利润
0 华东 A 2200.0 440.结果
1 华东 B 2050.0 410.0
2 华南 C 1550.0 310. 产品
3 华北 A 1100.0 220.0
4 华北 B 1800.0 360.()
多级索引形式的结果:
销售额 利润
地区 产品
华东 A 2200.0 440.0
B 2050.0 410.0
华南 C 1550.0 310.0
华北 A 1100.0 0
B 1800() 360.0
代码解析:
['地区', '产品']使用列表可以同时按多列分组。as_index=False时,结果是 DataFrame 格式,分组列作为普通列保留。- 多级索引形式更简洁,适合进行后续的数据分析操作。
示例 3:处理缺失值时的平均值计算
当数据中存在缺失值(NaN)时,mean() 会自动忽略这些缺失值进行计算。
实例
import pandas as pd
import numpy as np
# 创建包含缺失值的员工工资数据
data = {
'部门': ['销售', '销售', '销售', '技术', '技术', '技术', '行政', '行政'],
'工资': [5000, 6000, np.nan, 8000, 9000, np.nan, 4500, np.nan]
}
df = pd.DataFrame(data)
print("员工工资数据(包含缺失值):")
print(df)
print()
# 默认情况下,mean() 会忽略 NaN 值进行计算
avg_with_nan = df.groupby('部门')['工资'].mean()
print("默认计算平均值(忽略NaN):")
print(avg_with_nan)
print()
# 如果想包含 NaN 值作为 0 来计算,需要先填充
avg_filled = df.groupby('部门')['工资'].apply(lambda x: x.fillna(0).mean())
print("将NaN视为0后的平均工资:")
print(avg_filled)
print()
# 使用 skipna 参数(默认为 True)
# 如果设置 skipna=False,则所有含 NaN 的组都返回 NaN
# 注意:groupby 的 mean 没有 skipna 参数,但可以通过 fillna 实现类似效果
import numpy as np
# 创建包含缺失值的员工工资数据
data = {
'部门': ['销售', '销售', '销售', '技术', '技术', '技术', '行政', '行政'],
'工资': [5000, 6000, np.nan, 8000, 9000, np.nan, 4500, np.nan]
}
df = pd.DataFrame(data)
print("员工工资数据(包含缺失值):")
print(df)
print()
# 默认情况下,mean() 会忽略 NaN 值进行计算
avg_with_nan = df.groupby('部门')['工资'].mean()
print("默认计算平均值(忽略NaN):")
print(avg_with_nan)
print()
# 如果想包含 NaN 值作为 0 来计算,需要先填充
avg_filled = df.groupby('部门')['工资'].apply(lambda x: x.fillna(0).mean())
print("将NaN视为0后的平均工资:")
print(avg_filled)
print()
# 使用 skipna 参数(默认为 True)
# 如果设置 skipna=False,则所有含 NaN 的组都返回 NaN
# 注意:groupby 的 mean 没有 skipna 参数,但可以通过 fillna 实现类似效果
运行结果预期:
员工工资数据(包含缺失值): 部门 工资 0 销售 5000.0 1 销售 6000.0 2 销售 NaN 3 技术 销售 8000.0 4 技术 9000.0 5 技术 NaN 销售 行政 4500 .0 7 行政 NaN 默认计算平均值(忽略NA N): 部门 技术 8500.0 行政 4500.0 销售 5500.0 dtype: float64 将NaN视为0后的平均工资: 部门 技术 5666.666667 行政 2250.0 销售 3666.666667 dtype: float64
代码解析:
- 默认情况下,
mean()会自动忽略 NaN 值,不参与平均值的计算。 - 销售部门有2个有效值(5000, 6000),平均值为 5500。
- 如果需要将 NaN 视为 0 再计算平均值,可以使用
fillna(0)先填充缺失值。
示例 4:结合 transform 计算组内占比
可以通过 transform 方法将分组平均值广播回原数据的每一行,这在计算组内占比或与组平均值的差异时非常有用。
实例
import pandas as pd
# 创建学生成绩数据
data = {
'姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
'班级': ['A', 'A', 'A', 'B', 'B', 'B'],
'语文': [85, 92, 78, 88, 95, 82],
'数学': [90, 85, 92, 78, 88, 91]
}
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 计算每个班级的数学平均分,然后广播到每一行
df['班级数学平均分'] = df.groupby('班级')['数学'].transform('mean')
# 计算每个学生成绩与班级平均分的差值
df['与平均分差值'] = df['数学'] - df['班级数学平均分']
print("添加班级平均分和差值后的数据:")
print(df)
print()
# 计算每个学生的数学成绩占班级总分的百分比
df['班级内百分比'] = (df['数学'] / df['班级数学平均分'] * 100).round(2)
print("添加百分比后的数据:")
print(df)
# 创建学生成绩数据
data = {
'姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
'班级': ['A', 'A', 'A', 'B', 'B', 'B'],
'语文': [85, 92, 78, 88, 95, 82],
'数学': [90, 85, 92, 78, 88, 91]
}
df = pd.DataFrame(data)
print("学生成绩数据:")
print(df)
print()
# 计算每个班级的数学平均分,然后广播到每一行
df['班级数学平均分'] = df.groupby('班级')['数学'].transform('mean')
# 计算每个学生成绩与班级平均分的差值
df['与平均分差值'] = df['数学'] - df['班级数学平均分']
print("添加班级平均分和差值后的数据:")
print(df)
print()
# 计算每个学生的数学成绩占班级总分的百分比
df['班级内百分比'] = (df['数学'] / df['班级数学平均分'] * 100).round(2)
print("添加百分比后的数据:")
print(df)
运行结果预期:
学生成绩数据: 姓名 班级 语文 数学 0 张三 A 85 保持 1 李四 A 92 索引 2 王五 A 索引 3 平均值 赵六 B 计算 78 4 孙七 B 95 88 5 周八 B 82 91 添加班级平均分和差值后的数据: 姓名 班级 语文 数学 班级数学平均分 与平均分差值 0 张三 A 85 90 89.000000 1.000000 1 李四 A 92 85 89.重新分组 -4.000000 3 王五 A 78 92 89.000000 3.000000 4 赵六 B 88 78 85.666667 -7.666667 5 孙七 B 95 88 85.666667 2.333333 6 先 B 82 91 85.666667 5.333333 添加百分比后的数据: 班级 班级 数学 班级数学平均分 与平均分差值 班级内百分比 0 A 10000 90 89.0 1.0 101.12 1 A 0.3 索引
代码解析:
transform('mean')会将每个分组的平均值计算出来,然后广播回原数据的每一行。- 这样每个学生都能知道其所在班级的平均分,便于进行比较。
- 这种方法在计算"个体在群体中的位置"等分析场景中非常实用。
注意事项:
mean()函数默认会忽略 NaN 值进行计算。如果数据中全是缺失值,则返回 NaN。与sum()不同,mean()没有min_count参数。

Pandas 常用函数