查看全课大纲(第 56 / 101 节)
- 1.数据分析基本概念
- 2.学习数据分析的一般路线
- 3.数据分析的流程
- 4.数据类型
- 5.环境部署(1)
- 6.环境部署(2)
- 7.课程介绍
- 8.TXT文件操作
- 9.JSON文件操作
- 10.CSV文件操作
- 11.Excel文件操作
- 12.数据库及SQL常用语法
- 13.数据库基本操作
- 14.数据库多表连接
- 15.实战:欧洲职业足球数据库分析
- 16.爬虫简介
- 17.URL管理模块
- 18.网页下载模块
- 19.网页解析模块(1)
- 20.网页解析模块(2)
- 21.Scrapy简介
- 22.Scrapy使用步骤(1)
- 23.Scrapy使用步骤(2)
- 24.Scrapy使用步骤(3)
- 25.Scrapy使用步骤(4)
- 26.实战:获取国内城市空气质量指数数据
- 27.NumPy和SciPy介绍
- 28.多维数组
- 29.多维数组操作
- 30.NumPy的常用方法
- 31.向量化介绍
- 32.向量化及通用函数
- 33.实战:2016美国大选分析
- 34.数据结构-Series
- 35.数据结构-DataFrame
- 36.数据结构-Index
- 37.Series的索引操作
- 38.DataFrame的索引操作
- 39.索引操作总结
- 40.运算与对齐
- 41.函数应用操作(1) -- map
- 42.函数应用操作 (2) -- apply applymap
- 43.文件读写操作
- 44.排序操作
- 45.数据清洗--处理缺失数据
- 46.数据清洗--处理重复数据
- 47.数据清洗--替换数据
- 48.常用统计方法(1) -- describe quantile
- 49.常用统计方法(2) -- sum mean median count
- 50.常用统计方法(3) -- max min idxmax idxmin
- 51.常用统计方法(4) -- mad var std cumsum
- 52.实战:全球食品数据分析
- 53.层级索引
- 54.分组与聚合介绍
- 55.分组操作(1) -- GroupBy对象及常用聚合操作
- 56.分组操作(2) -- 自定义分组及聚合操作
- 57.透视表介绍
- 58.透视表操作
- 59.数据规整(1) -- 数据合并concat
- 60.数据规整(2) -- 数据连接merge
- 61.数据重构(3) -- 数据重构stack unstack
- 62.实战:互联网电影资料库分析
- 63.探索性数据分析EDA介绍
- 64.EDA的目的
- 65.EDA常用工具
- 66.Matplotlib绘图基本介绍
- 67.Matplotlib画布
- 68.散点图和柱状图的绘制
- 69.直方图的绘制
- 70.矩阵绘图
- 71.子图的使用
- 72.Matplotlib颜色、标记、线型
- 73.Matplotlib坐标刻度、标签、图例、标题
- 74.Seaborn介绍
- 75.数据集分布可视化(1) -- 单变量分布、双变量分布
- 76.数据集分布可视化(2) -- 变量关系可视化
- 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
- 78.交互式数据可视化工具Bokeh介绍
- 79.Bokeh绘制散点图、柱状图、盒子图、弦图
- 80.Bokeh绘制常用图形元素
- 81.3D绘图 -- mplot3d
- 82.3D曲线可视化
- 83.3D散点图可视化
- 84.3D柱状图可视化
- 85.Pandas绘图
- 86.实战:Lending Club借贷数据探索性分析及可视化
- 87.机器学习介绍及应用场景
- 88.机器学习建模介绍 (1) -- 分类
- 89.机器学习建模介绍 (2) -- 回归
- 90.机器学习建模介绍 (3) -- 聚类
- 91.机器学习分类
- 92.机器学习工具scikit-learn
- 93.使用scikit-learn的流程
- 94.数据集准备及划分
- 95.模型选择
- 96.数据预处理及特征工程
- 97.过拟合与欠拟合
- 98.模型调参介绍
- 99.模型调参方法
- 100.模型测试及评价
- 101.实战:通过移动设备行为数据预测性别和年龄
分组操作(2) -- 自定义分组及聚合操作
约 12 分钟
分组操作(2)——自定义分组及聚合操作
小象实战讲义 · Python数据分析实战
在上一节中,我们掌握了Pandas分组操作的基本方法。然而,现实数据分析中,我们常常需要根据更复杂的规则对数据进行分组,或者执行非标准的聚合计算。本节将带你深入分组操作的高级应用,学习如何通过自定义规则进行分组,以及如何使用agg()函数实现灵活多样的聚合操作,从而应对更复杂的分析需求。
💡 核心导读
- 自定义分组:学习两种实现自定义分组的方法,包括直接向
groupby()传入函数,以及先构造分组列再分组。 agg()函数详解:掌握agg()函数的核心用法,它是实现灵活聚合操作的“瑞士军刀”。- 多聚合与列定制:了解如何一次性对分组数据执行多个聚合操作,并为不同列指定不同的聚合函数。
- 自定义聚合函数:学习如何编写并使用自定义函数进行聚合,以获取更深层次的数据洞察。
自定义分组
在标准的分组操作中,我们通常按某一列或多列的唯一值进行分组。但有时,我们需要根据更复杂的业务逻辑或自定义规则来划分数据组。例如,将连续数值(如幸福指数)划分为“高”、“中”、“低”三档,然后按档位进行分析。Pandas提供了两种主要方法来实现自定义分组。
方法一:向groupby()传入自定义函数
这种方法的核心是:groupby()可以接受一个函数作为分组依据。该函数会应用于索引(index)的每个元素,并根据函数的返回值进行分组。
让我们通过一个具体的例子来理解。假设我们有一份关于国家幸福指数的数据,我们希望根据“幸福指数”(Happiness Score)的高低进行自定义分组。
首先,我们构造一份简化的示例数据,并定义分组规则。
import pandas as pd
import numpy as np
# 构造示例数据:国家、区域、幸福排名、幸福指数
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 自定义分组规则函数
def get_score_group(score):
"""根据幸福指数返回分组标签"""
if score <= 7.2:
score_group = 'low'
elif score <= 7.5:
score_group = 'middle'
else:
score_group = 'high'
return score_group
# 方法1:将'Happiness Score'设为索引,然后按自定义函数分组
data_score_as_index = data.set_index('Happiness Score')
group_sizes = data_score_as_index.groupby(get_score_group).size()
print("按自定义函数分组结果(方法1):")
print(group_sizes)按自定义函数分组结果(方法1):
Happiness Score
high 3
middle 7
dtype: int64关键点解析:
- 操作对象是索引:自定义函数
get_score_group被应用于data_score_as_index的索引(即Happiness Score列的值)。 - 分组依据是函数返回值:函数返回
'low'、'middle'或'high',数据将根据这三个返回值被分为三组。 - 结果:从输出可见,我们的示例数据中,幸福指数“高”(high,得分 > 7.5)的国家有3个,“中”(middle,7.2 < 得分 ≤ 7.5)的国家有7个,没有“低”(low,得分 ≤ 7.2)分组。
方法二:先构造分组列,再分组
这是项目实践中更常用、更直观的方法。思路是:先利用apply()等方法,在DataFrame中新增一列,该列的值就是我们的自定义分组标签,然后再对这一新列进行常规的groupby操作。
import pandas as pd
import numpy as np
# 构造示例数据
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 自定义分组规则函数
def get_score_group(score):
"""根据幸福指数返回分组标签"""
if score <= 7.2:
score_group = 'low'
elif score <= 7.5:
score_group = 'middle'
else:
score_group = 'high'
return score_group
# 方法2:先创建分组列,再按该列分组
data['score_group'] = data['Happiness Score'].apply(get_score_group)
print("添加分组列后的数据(最后5行):")
print(data.tail())
print("\n按分组列分组结果(方法2):")
print(data.groupby('score_group').size())添加分组列后的数据(最后5行):
Country Region Happiness Rank Happiness Score score_group
5 Netherlands Western Europe 6 7.284 middle
6 Canada North America 7 7.278 middle
7 New Zealand Oceania 8 7.267 middle
8 Sweden Western Europe 9 7.231 middle
9 Australia Oceania 10 7.223 middle
按分组列分组结果(方法2):
score_group
high 3
middle 7
dtype: int64方法对比与选择:
- 方法一更简洁,但要求分组依据的列必须是索引,理解上稍绕。
- 方法二步骤清晰,新增的列直观可见,便于后续检查和复用,是工程实践中的首选。
自定义聚合操作
在基础分组中,我们使用.max()、.min()、.mean()等方法进行聚合。实际上,这些方法都是agg()函数的快捷方式。agg()(aggregation的缩写)是Pandas中功能更强大、更灵活的聚合接口。
认识agg()函数
agg()函数可以接受多种形式的参数:单个函数、函数列表、字典等,从而实现从简单到复杂的聚合需求。
1. 基础聚合与agg()等价形式
import pandas as pd
import numpy as np
# 构造示例数据
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 等价操作:按区域分组,求最大值
max_by_region_direct = data.groupby('Region').max()
max_by_region_agg = data.groupby('Region').agg(np.max)
print("直接使用.max()方法:")
print(max_by_region_direct[['Happiness Rank', 'Happiness Score']])
print("\n使用agg(np.max)方法:")
print(max_by_region_agg[['Happiness Rank', 'Happiness Score']])直接使用.max()方法:
Happiness Rank Happiness Score
Region
North America 7 7.278
Oceania 10 7.267
Western Europe 9 7.769
使用agg(np.max)方法:
Happiness Rank Happiness Score
Region
North America 7 7.278
Oceania 10 7.267
Western Europe 9 7.769两种方式结果完全一致,agg()提供了更明确的聚合意图表达。
2. 传入函数列表:一次性完成多聚合
agg()的强大之处在于可以一次性对同一列执行多个聚合计算。
import pandas as pd
import numpy as np
# 构造示例数据
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 使用agg()函数,传入函数列表进行多聚合操作
multi_agg = data.groupby('Region')['Happiness Score'].agg([np.max, np.min, np.mean])
print("按区域分组的多聚合统计(最大值、最小值、均值):")
print(multi_agg)按区域分组的多聚合统计(最大值、最小值、均值):
max min mean
Region
North America 7.278 7.278 7.278000
Oceania 7.267 7.223 7.245000
Western Europe 7.769 7.231 7.488571输出结果中的 max、min、mean 列,分别是 np.max、np.min、np.mean 聚合函数计算出的结果。(补充版本口径:旧版 pandas 会用 amax/amin 这样的函数名作列名,新版已按 max/min 输出——以你环境实际打印为准。)
3. 传入字典:为不同列指定不同聚合函数
当DataFrame有多列时,我们可能希望对不同列应用不同的聚合操作。这时,可以向agg()传入一个字典,其中键为列名,值为该列要应用的聚合函数。
import pandas as pd
import numpy as np
# 构造示例数据
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 使用字典为不同列指定不同的聚合函数
dict_agg = data.groupby('Region').agg({
'Happiness Score': np.mean, # 幸福指数求均值
'Happiness Rank': np.max # 排名求最大值(即最差排名)
})
print("按区域分组,不同列使用不同聚合函数:")
print(dict_agg)按区域分组,不同列使用不同聚合函数:
Happiness Score Happiness Rank
Region
North America 7.278000 7
Oceania 7.245000 10
Western Europe 7.488571 94. 传入自定义聚合函数
最灵活的方式是传入自定义函数。这允许我们实现任何复杂的、非标准的聚合逻辑。
例如,我们想分析每个区域内幸福排名的“两极分化”程度,可以计算每个组内排名最大值与最小值的差值(极差)。
import pandas as pd
import numpy as np
# 构造示例数据
data = pd.DataFrame({
'Country': ['Finland', 'Denmark', 'Switzerland', 'Iceland', 'Norway', 'Netherlands', 'Canada', 'New Zealand', 'Sweden', 'Australia'],
'Region': ['Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'Western Europe', 'North America', 'Oceania', 'Western Europe', 'Oceania'],
'Happiness Rank': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'Happiness Score': [7.769, 7.600, 7.554, 7.494, 7.488, 7.284, 7.278, 7.267, 7.231, 7.223]
})
# 自定义聚合函数:计算最大值与最小值的差值(极差)
def max_min_diff(x):
"""计算序列中最大值与最小值的差值"""
return x.max() - x.min()
# 应用自定义聚合函数:计算每个区域幸福排名的极差
rank_diff_by_region = data.groupby('Region')['Happiness Rank'].agg(max_min_diff)
print("按区域分组,幸福排名的极差(最大值-最小值):")
print(rank_diff_by_region)按区域分组,幸福排名的极差(最大值-最小值):
Region
North America 0
Oceania 2
Western Europe 8
Name: Happiness Rank, dtype: int64结果解读:Western Europe地区幸福排名的极差为8(从第1名到第9名),说明该区域内国家的幸福水平分布范围较广。而North America地区(本例中只有加拿大)极差为0,Oceania地区极差为2,分布相对集中。
📝 动手练一练
- 概念辨析:在“自定义分组”的两种方法中,方法一要求分组依据的列必须是索引,而方法二则是在数据中新增一列。请简述在什么场景下你会优先选择方法二?为什么?
👉 点击查看参考答案
在大多数项目实践场景中,我会优先选择方法二(先构造分组列)。原因如下:
- 直观清晰:新增的列直接呈现在DataFrame中,分组依据一目了然,便于代码审查和数据验证。
- 便于复用:构造好的分组列可以保存下来,供后续不同的分析步骤使用,避免重复计算。
- 灵活性高:不依赖于索引的设置,对数据的原始结构改动小,更符合“数据管道”的处理思想。
- 易于调试:如果分组规则复杂,可以先单独测试
apply函数在新列上的结果是否正确,再执行分组,降低了调试难度。
- 动手实践:假设我们想分析“幸福指数的稳定性”,定义一个自定义聚合函数,计算每个区域幸福指数的变异系数(标准差/均值)。请基于下面的示例数据,编写代码实现这一分析。
import pandas as pd
import numpy as np
# 示例数据
data = pd.DataFrame({
'Region': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C'],
'Happiness Score': [7.8, 7.9, 7.7, 6.5, 6.6, 6.4, 5.0, 9.0]
})
# 请在此处补充你的代码👉 点击查看参考答案
import pandas as pd
import numpy as np
# 示例数据
data = pd.DataFrame({
'Region': ['A', 'A', 'A', 'B', 'B', 'B', 'C', 'C'],
'Happiness Score': [7.8, 7.9, 7.7, 6.5, 6.6, 6.4, 5.0, 9.0]
})
# 自定义聚合函数:计算变异系数
def coefficient_of_variation(x):
"""计算变异系数:标准差/均值"""
# 注意:为避免除零错误,实际应用中需考虑均值接近0的情况
return x.std() / x.mean()
# 应用自定义函数
cv_result = data.groupby('Region')['Happiness Score'].agg(coefficient_of_variation)
print("各区域幸福指数变异系数:")
print(cv_result)各区域幸福指数变异系数:
Region
A 0.012821
B 0.015385
C 0.404061
Name: Happiness Score, dtype: float64结果解读:区域C的变异系数远高于A和B,说明区域C内国家的幸福指数波动非常大(从5.0到9.0),稳定性最差。区域A的变异系数最小,幸福指数最稳定。
本章小结
本节我们深入探讨了Pandas分组操作中更高级、更灵活的部分——自定义分组与自定义聚合。掌握这些技能,能让你在面对复杂多变的业务分析需求时游刃有余。
📋 行动清单
- 练习自定义分组:找一份包含数值型评分的数据,尝试编写函数将其分为“优、良、中、差”等级,并用两种方法实现分组统计。
- 掌握
agg()的多种用法:对一个分组对象,分别使用单个函数、函数列表和字典参数调用agg(),观察输出结果的异同。 - 设计一个自定义聚合指标:结合你的业务领域(如电商、金融、社交),思考一个非标准的聚合需求(如“连续上涨天数”、“用户活跃度得分”),并尝试用自定义函数在分组中实现它。
—— 小象教研组
配套资料 · 直接下载
课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。
- 下载本节课件:分组操作(2) -- 自定义分组及聚合操作PDF · 164KB
- 下载全套课件打包(第1-5章)ZIP · 12.8MB
- 下载全套课件打包(第6-8章)ZIP · 15MB
- 下载实战数据集:AppleStore 应用商城分析ZIP · 329KB
- 下载实战数据集:女性服装电商分析ZIP · 2.8MB
- 下载Python 数据分析环境搭建指南PDF · 2MB
- 下载Scrapy 安装教程PDF · 12.7MB
- 下载附加实战项目:AppleStore 应用商城数据分析ZIP · 0.3MB · ipynb + CSV 数据
- 下载附加实战项目:银行电话营销数据分析ZIP · 0.4MB · ipynb + CSV 数据
- 下载附加实战项目:女性服装电商评论数据分析ZIP · 2.7MB · ipynb + CSV 数据
- 下载附加实战项目:美国化学学会杂志数据分析ZIP · 34.2MB · ipynb + SQLite 数据库