四时宝库

程序员的知识宝库

分类分组汇总一个函数搞定!详解Pandas的Groupby

Pandas 是 Python 中强大的数据分析库,其 GroupBy 功能能够帮助用户对数据集进行分组并执行各种聚合操作。本文通过 NYC 职位数据集(包含职位 ID、职位名称、发布机构、职位类型以及薪资范围等信息)为例,详细讲解 GroupBy 的工作原理及应用方法,并在关键步骤中插入示例数据表以增强理解。

准备工作

在使用 GroupBy 功能之前,需要导入 Pandas 库并加载数据集。以下是导入 NYC 职位数据集的代码:

import pandas as pd

# 加载 NYC 职位数据集
data = pd.read_csv('nyc_jobs.csv')

示例数据表

以下是 NYC 职位数据集的一个简化示例,展示其主要列:

Job ID

Agency

Civil Service Title

Posting Type

Salary Range From

Salary Range To

Job Category

510376

Admin for Children's Svcs

Social Worker

External

42731

50000

Social Services

510377

Human Rights Commission

Analyst

Internal

55000

65000

Legal Affairs

510378

Admin for Children's Svcs

Case Worker

Internal

45000

52000

Social Services

510379

Board of Correction

Inspector

External

60000

70000

Public Safety

GroupBy 的基本概念

GroupBy 功能允许用户根据指定列将数据集分割为多个子集,并对每个子集应用聚合函数(如均值、中位数等)。然而,初次使用 GroupBy 时,返回结果可能难以直接理解。例如:

# 按 Agency 列进行分组
grouped = data.groupby('Agency')
print(grouped)

运行上述代码,返回的是一个
pandas.core.groupby.generic.DataFrameGroupBy 对象,而非直观的数据表。这是因为 GroupBy 将数据集按 Agency 分割成多个子集,但未指定如何处理这些子集。

应用聚合函数

为了使分组结果更有意义,可以对分组应用聚合函数。例如,计算每个机构的 Salary Range From 列的均值:

# 计算每个机构的薪资范围均值
mean_salary = data.groupby('Agency')['Salary Range From'].mean()
print(mean_salary)

示例结果表

假设对上述示例数据执行此操作,结果可能如下:

Agency

Salary Range From (Mean)

Admin for Children's Svcs

43865.5

Board of Correction

60000.0

Human Rights Commission

55000.0

如果需要对所有数值列计算均值,可以省略列名,Pandas 会自动处理所有数值列:

# 对所有数值列计算均值
mean_all = data.groupby('Agency').mean()
print(mean_all)

示例结果表(多列均值)

Agency

Job ID (Mean)

Salary Range From (Mean)

Salary Range To (Mean)

Admin for Children's Svcs

510377.0

43865.5

51000.0

Board of Correction

510379.0

60000.0

70000.0

Human Rights Commission

510377.0

55000.0

65000.0

Pandas 支持多种聚合函数,包括均值(mean)、中位数(median)、最小值(min)、最大值(max)和求和(sum)等。更多操作可参考 Pandas GroupBy 文档。

应用多个聚合函数

可以同时对分组应用多个聚合函数。例如,计算每个机构的薪资范围均值和中位数:

# 应用多个聚合函数
result = data.groupby('Agency')['Salary Range From'].agg(['mean', 'median'])
print(result)

示例结果表

Agency

mean

median

Admin for Children's Svcs

43865.5

43865.5

Board of Correction

60000.0

60000.0

Human Rights Commission

55000.0

55000.0

自定义函数与分组

用户可以通过 apply 方法将自定义函数应用到分组。例如,定义一个计算均值的函数:

# 定义自定义函数
def custom_mean(group):
    return group.mean()

# 应用自定义函数
result = data.groupby('Agency')['Salary Range From'].apply(custom_mean)
print(result)

要查看分组的结构,可以遍历每个分组:

# 查看每个分组的内容
for name, group in data.groupby('Agency'):
    print(f"Group: {name}")
    print(group['Salary Range From'])
    print("***")

示例输出

Group: Admin for Children's Svcs
0    42731
2    45000
Name: Salary Range From, dtype: int64
***
Group: Board of Correction
3    60000
Name: Salary Range From, dtype: int64
***
Group: Human Rights Commission
1    55000
Name: Salary Range From, dtype: int64
***

多列分组

GroupBy 支持按多列分组。例如,按 Agency 和 Posting Type 分组:

# 按多列分组并计算均值
result = data.groupby(['Agency', 'Posting Type'])['Salary Range From'].mean()
print(result)

示例结果表

Agency

Posting Type

Salary Range From (Mean)

Admin for Children's Svcs

External

42731.0

Admin for Children's Svcs

Internal

45000.0

Board of Correction

External

60000.0

Human Rights Commission

Internal

55000.0

若不希望分组列成为多级索引,可设置 as_index=False:

# 保留分组列作为普通列
result = data.groupby(['Agency', 'Posting Type'], as_index=False)['Salary Range From'].mean()
print(result)

示例结果表(普通列)

Agency

Posting Type

Salary Range From

Admin for Children's Svcs

External

42731.0

Admin for Children's Svcs

Internal

45000.0

Board of Correction

External

60000.0

Human Rights Commission

Internal

55000.0

提取分组信息

GroupBy 对象提供多种方法提取分组信息。例如,获取每个分组的首行:

# 获取每个分组的首行
first_rows = data.groupby('Agency').first()
print(first_rows)

示例结果表

Agency

Job ID

Civil Service Title

Posting Type

Salary Range From

Salary Range To

Job Category

Admin for Children's Svcs

510376

Social Worker

External

42731

50000

Social Services

Board of Correction

510379

Inspector

External

60000

70000

Public Safety

Human Rights Commission

510377

Analyst

Internal

55000

65000

Legal Affairs

获取特定分组:

# 获取特定分组
human_rights_group = data.groupby('Agency').get_group('Human Rights Commission')
print(human_rights_group)

示例结果表

Job ID

Civil Service Title

Posting Type

Salary Range From

Salary Range To

Job Category

510377

Analyst

Internal

55000

65000

Legal Affairs

使用 Grouper 处理时间序列

对于时间序列数据,pd.Grouper 提供灵活的分组方式。以下是一个模拟时间序列数据的示例:

# 创建模拟时间序列数据
time_data = pd.DataFrame({
    'Publish Date': ['2000-01-02', '2000-01-02', '2000-01-09', '2000-01-16'],
    'Price': [10, 20, 15, 25]
})
time_data['Publish Date'] = pd.to_datetime(time_data['Publish Date'])

# 按周分组并计算均值
weekly_groups = time_data.groupby(pd.Grouper(key='Publish Date', freq='1W'))['Price'].mean()
print(weekly_groups)

示例结果表

Publish Date

Price (Mean)

2000-01-02

15.0

2000-01-09

15.0

2000-01-16

25.0

通过调整 freq 参数(如 2W 表示每两周),可以改变分组频率:

# 按两周分组
biweekly_groups = time_data.groupby(pd.Grouper(key='Publish Date', freq='2W'))['Price'].mean()
print(biweekly_groups)

示例结果表

Publish Date

Price (Mean)

2000-01-02

15.0

2000-01-16

20.0

优化 GroupBy 性能

对于大型数据集,GroupBy 操作可能较慢。默认情况下,GroupBy 会对结果排序,增加计算时间。设置 sort=False 可提高性能:

# 禁用排序以提高性能
fast_group = data.groupby('Agency', sort=False)['Salary Range From'].mean()
print(fast_group)

总结

Pandas 的 GroupBy 功能是数据分析的强大工具,支持以下操作:

  • 按单列或多列分组;
  • 应用内置或自定义聚合函数;
  • 处理时间序列数据;
  • 优化大型数据集性能。
<script type="text/javascript" src="//mp.toutiao.com/mp/agw/mass_profit/pc_product_promotions_js?item_id=7523781179733787145"></script>

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接