在 Python 中,对数据进行分组操作时,pandas 库的 groupby() 是最常用和最强大的工具,你提到的“列名”就是分组的依据。
下面我将详细解释如何使用 groupby,从基础到进阶,并提供清晰的示例。
核心概念
groupby 的核心思想是 “分-组-合” (Split-Apply-Combine):
- 分: 根据
by参数中指定的一个或多个列名,将 DataFrame 划分成多个组。 - 组: 对每个独立的组应用某种操作(例如计算平均值、求和、计数等)。
- 合: 将所有组操作的结果重新组合成一个单一的数据结构(通常是新的 DataFrame 或 Series)。
基础用法:按单个列名分组
这是最常见的情况,你只需要将列名作为字符串传递给 groupby()。
示例数据
我们创建一个示例 DataFrame:
import pandas as pd
# 创建一个示例 DataFrame
data = {
'Department': ['Sales', 'HR', 'Sales', 'IT', 'HR', 'IT', 'Sales'],
'Employee': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Frank', 'Grace'],
'Salary': [70000, 80000, 72000, 90000, 85000, 95000, 78000],
'Years_of_Experience': [5, 7, 6, 10, 8, 12, 5]
}
df = pd.DataFrame(data)
print("原始 DataFrame:")
print(df)
输出:
原始 DataFrame:
Department Employee Salary Years_of_Experience
0 Sales Alice 70000 5
1 HR Bob 80000 7
2 Sales Charlie 72000 6
3 IT David 90000 10
4 HR Eve 85000 8
5 IT Frank 95000 12
6 Sales Grace 78000 5
按部门分组并计算平均薪资
# 按 'Department' 列分组,并计算每个组的 'Salary' 的平均值
avg_salary_by_dept = df.groupby('Department')['Salary'].mean()
print("\n按部门分组的平均薪资:")
print(avg_salary_by_dept)
输出:
按部门分组的平均薪资:
Department
HR 82500.0
IT 92500.0
Sales 73333.333333
Name: Salary, dtype: float64
代码解析:
df.groupby('Department'): 这一步告诉 pandas 按Department列的值('Sales', 'HR', 'IT')来创建组。['Salary']: 这是在分组后,选择我们想要操作的列,我们只关心薪资数据。.mean(): 这是我们对每个组的Salary列要执行的操作——计算平均值。
按多个列名分组
你也可以使用多个列名进行分组,这会创建一个多级索引。
示例:按部门和经验范围分组
我们添加一个表示经验范围的列:
# 添加一个经验范围列
df['Experience_Level'] = pd.cut(df['Years_of_Experience'],
bins=[0, 5, 10, 15],
labels=['Junior', 'Mid', 'Senior'])
print("\n添加经验范围后的 DataFrame:")
print(df)
输出:
添加经验范围后的 DataFrame:
Department Employee Salary Years_of_Experience Experience_Level
0 Sales Alice 70000 5 Junior
1 HR Bob 80000 7 Mid
2 Sales Charlie 72000 6 Mid
3 IT David 90000 10 Senior
4 HR Eve 85000 8 Mid
5 IT Frank 95000 12 Senior
6 Sales Grace 78000 5 Junior
按部门和经验级别分组并计算薪资总和
# 按 'Department' 和 'Experience_Level' 分组,并计算薪资总和
total_salary_by_dept_level = df.groupby(['Department', 'Experience_Level'])['Salary'].sum()
print("\n按部门和经验级别分组的薪资总和:")
print(total_salary_by_dept_level)
输出:
按部门和经验级别分组的薪资总和:
Department Experience_Level
HR Junior NaN
Mid 165000
Senior NaN
IT Junior NaN
Mid NaN
Senior 185000
Sales Junior 148000
Mid 72000
Senior NaN
Name: Salary, dtype: float64
代码解析:
df.groupby(['Department', 'Experience_Level']): 我们传入了一个列表,包含了两个列名,pandas 会先按Department分,然后在每个Department内部再按Experience_Level分。- 结果是一个带有
MultiIndex(多级索引) 的 Series。
常用的聚合函数
对分组后的数据,你可以应用多种聚合函数:
| 函数 | 描述 |
|---|---|
.sum() |
计算总和 |
.mean() |
计算平均值 |
.median() |
计算中位数 |
.min() / .max() |
计算最小值 / 最大值 |
.count() |
计算非空值的数量 |
.std() / .var() |
计算标准差 / 方差 |
.first() / .last() |
获取组的第一个值 / 最后一个值 |
.describe() |
生成描述性统计信息 |
示例:一次性计算多个统计量
使用 .agg() 方法,你可以对同一列应用多个聚合函数,或者对不同列应用不同的函数。
# 对每个部门,计算薪资的平均值和最大值,以及员工人数
agg_results = df.groupby('Department').agg(
Avg_Salary=('Salary', 'mean'),
Max_Salary=('Salary', 'max'),
Employee_Count=('Employee', 'count')
)
print("\n各部门的聚合统计:")
print(agg_results)
输出:
各部门的聚合统计:
Avg_Salary Max_Salary Employee_Count
Department
HR 82500.0 85000 2
IT 92500.0 95000 2
Sales 73333.333333 78000 3
代码解析:
.agg(): 允许你进行更复杂的聚合。Avg_Salary=('Salary', 'mean'): 这是一个命名元组,意思是,创建一个名为Avg_Salary的新列,它的值是通过Salary列应用mean函数计算得到的。- 这种方式非常灵活和清晰。
遍历分组对象
如果你想对每个组进行自定义的、复杂的操作,可以遍历 groupby 对象。
# 遍历分组对象
for name, group in df.groupby('Department'):
print(f"\n--- 组名: {name} ---")
print("该组的数据:")
print(group)
输出:
--- 组名: HR ---
该组的数据:
Department Employee Salary Years_of_Experience Experience_Level
1 HR Bob 80000 7 Mid
4 HR Eve 85000 8 Mid
--- 组名: IT ---
该组的数据:
Department Employee Salary Years_of_Experience Experience_Level
3 IT David 90000 10 Senior
5 IT Frank 95000 12 Senior
--- 组名: Sales ---
该组的数据:
Department Employee Salary Years_of_Experience Experience_Level
0 Sales Alice 70000 5 Junior
2 Sales Charlie 72000 6 Mid
6 Sales Grace 78000 5 Junior
代码解析:
groupby()返回一个迭代器。- 每次迭代,它会返回一个元组,包含
(组名, 该组的数据)。 name是分组的键(如 'HR', 'IT')。group是一个 DataFrame,包含了属于该组的所有行。
| 需求 | 代码示例 | 说明 |
|---|---|---|
| 按单列分组 | df.groupby('ColumnName') |
最基础的分组方式。 |
| 按多列分组 | df.groupby(['Col1', 'Col2']) |
创建多级索引的分组。 |
| 选择特定列操作 | df.groupby('Dept')['Salary'].mean() |
分组后只对 Salary 列计算均值。 |
| 应用聚合函数 | .sum(), .mean(), .count() 等 |
对分组后的数据进行统计计算。 |
| 多列多聚合 | .agg(Avg=('Col', 'mean'), Max=('Col', 'max')) |
灵活地一次性计算多个统计量。 |
| 遍历处理 | for name, group in df.groupby(...): |
对每个组进行自定义的复杂操作。 |
掌握 pandas.DataFrame.groupby() 是进行数据分析的核心技能之一,它能让你高效地探索和理解数据集的结构和特征。
