现在位置: 首页 > Pandas 教程 > 正文

Pandas df.groupby() 函数

Pandas 常用函数 Pandas 常用函数


groupby() 是 Pandas 中最强大的分组操作函数之一,它允许你根据一个或多个列的值将数据分成不同的组,然后对每个组进行各种操作。

简单来说,groupby() 实现了"拆分-应用-合并"(Split-Apply-Combine)的工作流程:先把数据按条件拆分,对每个组应用相应的函数,最后把结果合并起来。

这在数据分析中非常常见,比如按部门统计员工平均工资、按月份统计销售额、按地区统计用户数量等。


基本语法与参数

groupby() 是 DataFrame 的成员函数,通过点运算符 . 来调用。调用后会返回一个 GroupBy 对象,这个对象本身不会直接显示结果,需要配合聚合函数一起使用。

语法格式

DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, observed=False, dropna=True)

参数说明

参数 类型 说明 默认值
by str、list 或 dict 用于分组的列名或列名列表。如果是字典或函数,则按其结果分组。 None
axis int 分组的轴方向,0 表示按行(默认),1 表示按列。 0
level int 或 str 如果是多层索引(MultiIndex),按指定层级分组。 None
as_index bool 如果为 True,分组列将作为返回结果的索引;如果为 False,分组列会作为普通列保留。 True
sort bool 是否对分组标签进行排序。设置为 False 可以提高性能。 True
group_keys bool 调用 apply() 时,是否在结果中添加分组键作为索引。 True
observed bool 如果为 True,则只显示分类变量的实际观测值,而不是所有可能的值。 False
dropna bool 如果为 True,则包含 NA/null 值的组将被丢弃。 True

返回值

  • 返回类型DataFrameGroupBySeriesGroupBy 对象
  • 说明:返回的是一个分组对象,不是最终结果。后续需要调用聚合函数(如 sum()mean()count() 等)才能得到具体的计算结果。

实例

让我们通过一系列从简单到复杂的例子,彻底掌握 groupby() 的用法。

示例 1:按单列分组

最基础的用法是按照某一列的值进行分组。假设我们有一个销售数据表,需要按地区统计总销售额。

实例

import pandas as pd

# 创建一个简单的销售数据 DataFrame
# 模拟一个包含地区、产品、销售额的表格
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100]
}

# 创建 DataFrame
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 按"地区"列分组,计算每个地区的总销售额
# as_index=True 表示地区作为索引返回
grouped = df.groupby('地区', as_index=True)['销售额'].sum()

print("按地区分组后的总销售额:")
print(grouped)
print()

# as_index=False 时,分组列会作为普通列保留
grouped_df = df.groupby('地区', as_index=False)['销售额'].sum()

print("as_index=False 时的结果:")
print(grouped_df)

运行结果预期:

原始数据:
  地区  产品   销售额
0  华东   B   2000
1  华南   C   1500
2  华北   A   1000
3  华东   B   1800
4  华南   C   2200
5  华北   A   1600
6  华东   A   1200
7  华南   B   2100

按地区分组后的总销售额:
地区
华东    7100
华南    7300
华北    3600
dtype: int64

as_index=False 时的结果:
   地区    销售额
0  华东    7100
1  华南    7300
2  华北    3600

代码解析:

  1. df.groupby('地区') 按照"地区"列的值将数据分成三组:华东、华南、华北。
  2. ['销售额'].sum() 表示只对"销售额"列进行求和聚合。
  3. as_index=True(默认值)时,返回的 Series 以地区作为索引;as_index=False 时,返回的 DataFrame 保留地区作为普通列,更适合后续处理。

示例 2:按多列分组

有时需要同时按多个列进行分组,比如按地区和产品统计销售额。

实例

import pandas as pd

# 创建销售数据
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南', '华北', '华东'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C', 'A', 'B'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600, 1200, 2100]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 按"地区"和"产品"两列分组,计算总销售额
# 使用列表指定多个分组列
grouped = df.groupby(['地区', '产品'], as_index=False)['销售额'].sum()

print("按地区和产品分组后的总销售额:")
print(grouped)
print()

# 使用 pivot_table 更直观地展示结果
pivot = df.pivot_table(values='销售额', index='地区', columns='产品', aggfunc='sum', fill_value=0)
print("使用 pivot_table 展示:")
print(pivot)

运行结果预期:

原始数据:
  地区  产品   销售额
0  华北   A   1000
1  华东   B   2000
2  华南   C   1500
3  华北   B   1800
4  华东   A   2200
5  华南   C   1600
6  华北   A   1200
7  华东   B   2100

按地区和产品分组后的总销售额:
   地区  产品   销售额
0  华东   A   2200
1  华东   B   4100
2  华南   C   3100
3  华北   A   2200
4  华北   B   1800

使用 pivot_table 展示:
产品      A     B     C
地区
华北   2200  1800     0
华东   2200  4100     0
华南      0     0  3100

代码解析:

  • ['地区', '产品'] 使用列表可以同时按多列分组,结果会产生多级索引。
  • as_index=False 时,分组列会作为普通列保留在结果中,方便查看和后续处理。
  • pivot_table() 提供了类似的交叉表功能,可以将分组结果以更直观的方式呈现。

示例 3:使用字典和函数分组

groupby() 不仅可以按列名分组,还支持通过字典或函数来定义分组规则,这在需要自定义分组逻辑时非常有用。

实例

import pandas as pd

# 创建学生成绩数据
data = {
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', '周八'],
    '语文': [85, 92, 78, 88, 95, 82],
    '数学': [90, 85, 92, 78, 88, 91],
    '英语': [88, 90, 85, 92, 87, 89]
}
df = pd.DataFrame(data)

print("原始学生成绩数据:")
print(df)
print()

# 1. 使用字典进行自定义分组
# 假设我们要按照"姓氏"分组(张、李、王算一组,赵、孙、周算另一组)
def get_surname_group(name):
    """根据姓氏返回分组名称"""
    if name in ['张三', '李四', '王五']:
        return '第一组'
    else:
        return '第二组'

# 使用 apply 函数进行分组
grouped = df.groupby(get_surname_group).mean(numeric_only=True)
print("使用函数自定义分组(计算每组平均分):")
print(grouped)
print()

# 2. 使用字典映射特定列的分组
# 按数值区间将语文成绩分为"优秀"和"良好"两组
score_mapping = {
    '语文': lambda x: '优秀' if x >= 90 else '良好'
}

# 对语文列按条件分组
grouped_by_score = df.groupby(lambda x: '优秀' if df.loc[x, '语文'] >= 90 else '良好').mean(numeric_only=True)
print("按语文成绩分组(>=90为优秀):")
print(grouped_by_score)

运行结果预期:

原始学生成绩数据:
   姓名  语文  数学  英语
0  张三   85   90   88
1  李四   92   85   90
2  王五   78   92   85
3  赵六   88   78   92
4  孙七   95   88   87
5  周八   82   91   89

使用函数自定义分组(计算每组平均分):
              语文     数学     英语
姓名
第一组  85.000000  89.000000  87.666667
第二组  88.333333  85.666667  89.333333

按语文成绩分组(>=90为优秀):
              语文     数学     英语
语文
优秀   93.500000  86.500000  88.500000
良好   83.250000  89.500000  88.750000

代码解析:

  • 自定义函数分组可以处理复杂的分组逻辑,只要函数返回一个用于分组的值即可。
  • 使用 numeric_only=True 参数可以只对数值列进行聚合计算,避免对非数值列(如姓名)进行操作时出错。
  • 通过字典映射可以实现"按条件将不同列分成不同组"的需求。

示例 4:分组后迭代处理

有时候我们需要对每个分组进行更复杂的自定义操作,这时可以遍历分组对象。

实例

import pandas as pd

# 创建销售数据
data = {
    '地区': ['华北', '华东', '华南', '华北', '华东', '华南'],
    '产品': ['A', 'B', 'C', 'B', 'A', 'C'],
    '销售额': [1000, 2000, 1500, 1800, 2200, 1600]
}
df = pd.DataFrame(data)

print("原始数据:")
print(df)
print()

# 遍历每个分组进行处理
print("每个分组的详细信息:")
print("-" * 40)

for group_name, group_data in df.groupby('地区'):
    print(f"n分组名称: {group_name}")
    print(f"该组数据行数: {len(group_data)}")
    print(f"该组销售总额: {group_data['销售额'].sum()}")
    print(f"该组平均销售额: {group_data['销售额'].mean():.2f}")
    print("-" * 40)

运行结果预期:

原始数据:
  地区  产品   销售额
0  华东   B   2000
1  华南   C   1500
2  华北   A   1000
3  华东   B   1800
4  华南   C   2200
5  华北   B   1800

每个分组的详细信息:
----------------------------------------

分组名称: 华东
该组数据行数: 2
该组销售总额: 3800
该组平均销售额: 1900.00
----------------------------------------

分组名称: 华南
该组数据行数: 2
3700
1850.00
----------------------------------------

分组名称: 华北
该组数据行数: 2
2800
1400.00
----------------------------------------

代码解析:

  • groupby() 返回的分组对象可以直接迭代,每次迭代返回一个元组:(分组名, 该组的数据)。
  • 通过这种方式,可以对每个分组执行任意复杂的自定义操作。
  • 在实际应用中,这种方式常用于生成复杂的报表或进行数据清洗。

提示:groupby() 返回的 GroupBy 对象是"延迟执行"的,不会立即计算结果。只有调用聚合函数(如 sum()mean()count() 等)或进行迭代时才会真正执行计算。


Pandas 常用函数 Pandas 常用函数