![]()
26. groupby 基础
1. 概述
groupby是 Pandas 中最强大的功能之一,它实现了"拆分-应用-合并"(Split-Apply-Combine)操作模式,用于对数据进行分组聚合分析。
importpandasaspdimportnumpyasnp# 创建示例数据np.random.seed(42)df=pd.DataFrame({'部门':['技术','销售','技术','市场','销售','技术','市场','销售'],'姓名':['张三','李四','王五','赵六','钱七','孙八','周九','吴十'],'工资':[8000,12000,10000,15000,11000,9500,10500,12500],'年龄':[25,30,28,32,35,27,29,31],'绩效':['A','B','A','A','C','B','A','B']})print("原始数据:")print(df)
2. groupby 基础操作
2.1 单列分组
# 按部门分组grouped=df.groupby('部门')print("分组对象:",grouped)print(f"分组数:{len(grouped)}")# 查看各组forname,groupingrouped:print(f"\n部门:{name}")print(group)
2.2 多列分组
# 按部门和绩效分组grouped_multi=df.groupby(['部门','绩效'])for(dept,perf),groupingrouped_multi:print(f"\n部门={dept}, 绩效={perf}")print(group[['姓名','工资']])
3. 分组聚合
3.1 基础聚合函数
# 单列聚合print("各部门平均工资:")print(df.groupby('部门')['工资'].mean())print("\n各部门工资总和:")print(df.groupby('部门')['工资'].sum())print("\n各部门人数:")print(df.groupby('部门')['姓名'].count())print("\n各部门工资统计:")print(df.groupby('部门')['工资'].agg(['mean','sum','min','max','std']))
3.2 多列聚合
# 对多列应用相同聚合print("各部门工资和年龄统计:")print(df.groupby('部门')[['工资','年龄']].mean())# 对多列应用不同聚合print("\n各部门统计(工资求和,年龄平均):")print(df.groupby('部门').agg({'工资':'sum','年龄':'mean'}))
3.3 多种聚合函数
# 使用 agg 同时应用多个函数result=df.groupby('部门')['工资'].agg(['mean','median','min','max','std','count'])print("多种聚合:")print(result)# 重命名聚合列result=df.groupby('部门').agg(平均工资=('工资','mean'),最高工资=('工资','max'),最低工资=('工资','min'),人数=('姓名','count'))print("\n重命名聚合列:")print(result)
4. 分组后选择列
# 选择单列分组dept_avg_salary=df.groupby('部门')['工资'].mean()print("各部门平均工资:")print(dept_avg_salary)# 选择多列dept_stats=df.groupby('部门')[['工资','年龄']].agg(['mean','max'])print("\n各部门工资和年龄统计:")print(dept_stats)
5. 分组遍历
# 遍历分组dept_summary=[]forname,groupindf.groupby('部门'):summary={'部门':name,'人数':len(group),'平均工资':group['工资'].mean(),'最高工资':group['工资'].max(),'最年轻':group['年龄'].min()}dept_summary.append(summary)result=pd.DataFrame(dept_summary)print("分组遍历结果:")print(result)
6. 分组后获取特定组
# 获取特定组tech_group=df.groupby('部门').get_group('技术')print("技术部门:")print(tech_group)# 获取所有组的索引groups=df.groupby('部门').groupsprint("\n各组索引:")print(groups)
7. 完整示例:销售数据分析
# 创建销售数据np.random.seed(42)sales=pd.DataFrame({'日期':pd.date_range('2024-01-01',periods=100,freq='D'),'产品':np.random.choice(['产品A','产品B','产品C'],100),'地区':np.random.choice(['华东','华南','华北','西南'],100),'销售额':np.random.randint(1000,10000,100),'销量':np.random.randint(10,200,100),'销售员':np.random.choice(['张三','李四','王五'],100)})print("="*60)print("销售数据分析")print("="*60)print("\n原始数据:")print(sales.head())# 1. 按产品分组统计print("\n1. 各产品销售额统计:")product_stats=sales.groupby('产品').agg({'销售额':['sum','mean','max'],'销量':'sum'}).round(2)print(product_stats)# 2. 按地区分组统计print("\n2. 各地区销售情况:")region_stats=sales.groupby('地区').agg({'销售额':'sum','销量':'sum','销售员':'nunique'}).rename(columns={'销售员':'销售员数'})print(region_stats)# 3. 按产品和地区分组print("\n3. 产品×地区销售矩阵:")pivot=sales.groupby(['产品','地区'])['销售额'].sum().unstack()print(pivot)# 4. 按销售员分组print("\n4. 销售员业绩排名:")salesperson_stats=sales.groupby('销售员').agg({'销售额':'sum','销量':'sum'}).sort_values('销售额',ascending=False)print(salesperson_stats)# 5. 按月份分组(提取月份)sales['月份']=sales['日期'].dt.month monthly_stats=sales.groupby('月份').agg({'销售额':'sum','销量':'sum'})print("\n5. 月度销售趋势:")print(monthly_stats)
8. groupby 常用聚合函数
| 函数 | 说明 | 示例 |
|---|
mean() | 平均值 | df.groupby('A')['B'].mean() |
sum() | 求和 | df.groupby('A')['B'].sum() |
count() | 非空值计数 | df.groupby('A')['B'].count() |
size() | 行数计数(含空值) | df.groupby('A').size() |
min() | 最小值 | df.groupby('A')['B'].min() |
max() | 最大值 | df.groupby('A')['B'].max() |
std() | 标准差 | df.groupby('A')['B'].std() |
var() | 方差 | df.groupby('A')['B'].var() |
median() | 中位数 | df.groupby('A')['B'].median() |
first() | 第一个值 | df.groupby('A')['B'].first() |
last() | 最后一个值 | df.groupby('A')['B'].last() |
nunique() | 唯一值计数 | df.groupby('A')['B'].nunique() |
9. 总结
| 操作 | 方法 | 示例 |
|---|
| 单列分组 | groupby('col') | df.groupby('部门') |
| 多列分组 | groupby(['col1','col2']) | df.groupby(['部门','绩效']) |
| 单列聚合 | groupby('col')['val'].mean() | df.groupby('部门')['工资'].mean() |
| 多列聚合 | groupby('col')[['val1','val2']].mean() | df.groupby('部门')[['工资','年龄']].mean() |
| 多种聚合 | agg(['mean','sum']) | df.groupby('部门')['工资'].agg(['mean','sum']) |
| 不同列不同聚合 | agg({'A':'sum','B':'mean'}) | df.groupby('部门').agg({'工资':'sum','年龄':'mean'}) |
| 命名聚合 | agg(新列=('列','函数')) | df.groupby('部门').agg(平均工资=('工资','mean')) |
| 获取特定组 | get_group() | df.groupby('部门').get_group('技术') |