本文目录导读:

我来介绍使用Pandas进行数据分组分析的几个经典案例:
基础数据准备
import pandas as pd
import numpy as np
# 创建示例数据
data = {
'部门': ['销售部', '技术部', '销售部', '技术部', '市场部',
'销售部', '技术部', '市场部', '销售部', '市场部'],
'姓名': ['张三', '李四', '王五', '赵六', '钱七',
'孙八', '周九', '吴十', '郑一', '陈二'],
'性别': ['男', '女', '男', '男', '女',
'男', '女', '男', '女', '男'],
'年龄': [28, 32, 35, 27, 30, 45, 38, 29, 42, 33],
'薪资': [8000, 15000, 9000, 18000, 12000,
10000, 16000, 11000, 9500, 13000],
'入职日期': ['2020-01-15', '2019-03-20', '2021-06-01', '2018-09-10',
'2020-12-01', '2017-04-05', '2019-08-15', '2021-03-01',
'2018-11-20', '2020-07-10']
}
df = pd.DataFrame(data)
df['入职日期'] = pd.to_datetime(df['入职日期'])
print("原始数据:")
print(df)
基础分组聚合
# 按部门分组,计算统计量
print("各部门薪资统计:")
dept_stats = df.groupby('部门')['薪资'].agg(['count', 'mean', 'std', 'min', 'max'])
print(dept_stats)
print()
# 多重聚合
print("\n各部门详细统计:")
detailed_stats = df.groupby('部门').agg({
'薪资': ['mean', 'median', 'sum'],
'年龄': ['mean', 'min', 'max'],
'姓名': 'count'
})
print(detailed_stats)
多级分组报告
# 按部门和性别分组
print("按部门和性别分组统计:")
grouped = df.groupby(['部门', '性别']).agg({
'薪资': ['mean', 'sum'],
'年龄': 'mean',
'姓名': 'count'
}).rename(columns={'姓名': '人数'})
print(grouped)
print()
# 添加总计行
print("\n包含总计的报表:")
pivot_table = df.pivot_table(
values='薪资',
index='部门',
columns='性别',
aggfunc=['mean', 'count'],
margins=True,
margins_name='总计'
)
print(pivot_table)
分组排名和排序
# 各部门薪资排名
df['部门内排名'] = df.groupby('部门')['薪资'].rank(ascending=False)
print("各部门薪资排名:")
print(df[['部门', '姓名', '薪资', '部门内排名']].sort_values(['部门', '部门内排名']))
print()
# 各部门前N名
top_2_by_dept = df.groupby('部门').apply(
lambda x: x.nlargest(2, '薪资')
).reset_index(drop=True)
print("各部门薪资前2名:")
print(top_2_by_dept[['部门', '姓名', '薪资']])
分组条件统计
# 薪资高于平均的员工比例
dept_avg = df.groupby('部门')['薪资'].transform('mean')
df['是否高于平均'] = df['薪资'] > dept_avg
print("各部门高薪比例:")
high_ratio = df.groupby('部门')['是否高于平均'].mean()
print(high_ratio)
print()
# 年龄分组统计
age_bins = [20, 30, 40, 50]
age_labels = ['20-30岁', '30-40岁', '40-50岁']
df['年龄组'] = pd.cut(df['年龄'], bins=age_bins, labels=age_labels)
print("各年龄段薪资统计:")
age_group_stats = df.groupby('年龄组')['薪资'].describe()
print(age_group_stats)
时间序列分组
# 按入职年份分组
df['入职年份'] = df['入职日期'].dt.year
print("各年份入职员工薪资统计:")
yearly_stats = df.groupby('入职年份').agg({
'薪资': ['mean', 'sum'],
'姓名': 'count'
}).rename(columns={'姓名': '人数'})
print(yearly_stats)
print()
# 累计统计
cumulative_stats = df.sort_values('入职日期').groupby('部门')['薪资'].expanding().mean()
print("各部门薪资累积平均值:")
print(cumulative_stats)
综合报告生成
def generate_dept_report(df):
"""生成部门综合报告"""
report = {
'基础统计': df.groupby('部门').agg({
'薪资': ['mean', 'median', 'std'],
'年龄': ['mean', 'min', 'max'],
'姓名': 'count'
}).round(2),
'性别分布': pd.crosstab(df['部门'], df['性别'], margins=True)
.rename(columns={'margins': '总计'}, index={'margins': '总计'}),
'薪资区间': pd.cut(df['薪资'], bins=[0, 10000, 15000, 20000],
labels=['低薪', '中薪', '高薪']).groupby(df['部门']).value_counts()
.unstack(fill_value=0)
}
return report
# 生成报告
dept_report = generate_dept_report(df)
print("=== 部门综合报告 ===")
print("\n1. 基础统计:")
print(dept_report['基础统计'])
print("\n2. 性别分布:")
print(dept_report['性别分布'])
print("\n3. 薪资区间分布:")
print(dept_report['薪资区间'])
可视化分组结果
import matplotlib.pyplot as plt
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建分组统计图表
fig, axes = plt.subplots(2, 2, figsize=(12, 10))
# 各部门平均薪资
df.groupby('部门')['薪资'].mean().plot(kind='bar', ax=axes[0, 0])
axes[0, 0].set_title('各部门平均薪资')
axes[0, 0].set_ylabel('薪资')
# 各部门人数分布
df['部门'].value_counts().plot(kind='pie', ax=axes[0, 1], autopct='%1.1f%%')
axes[0, 1].set_title('各部门人数占比')
# 薪资分布箱线图
df.boxplot(column='薪资', by='部门', ax=axes[1, 0])
axes[1, 0].set_title('各部门薪资分布')
axes[1, 0].set_ylabel('薪资')
# 年龄分布
df.groupby('部门')['年龄'].mean().plot(kind='line', marker='o', ax=axes[1, 1])
axes[1, 1].set_title('各部门平均年龄')
axes[1, 1].set_ylabel('年龄')
plt.tight_layout()
plt.show()
高级分组技巧
# 自定义分组函数
def salary_level(amount):
if amount < 10000:
return '低'
elif amount < 15000:
return '中'
else:
return '高'
df['薪资等级'] = df['薪资'].apply(salary_level)
print("薪资等级分布:")
grade_stats = df.groupby(['部门', '薪资等级']).size().unstack(fill_value=0)
print(grade_stats)
print()
# 分组后应用自定义函数
print("各部门薪资分级统计:")
dept_grade_stats = df.groupby('部门')['薪资'].agg([
('平均值', 'mean'),
('中位数', 'median'),
('高薪人数', lambda x: (x > 15000).sum()),
('低薪人数', lambda x: (x < 10000).sum())
]).round(2)
print(dept_grade_stats)
完整报告导出
def export_dept_report_to_excel(df, filename='部门报告.xlsx'):
"""导出部门报告到Excel"""
with pd.ExcelWriter(filename, engine='openpyxl') as writer:
# 各部门汇总
summary = df.groupby('部门').agg({
'薪资': ['mean', 'sum', 'count'],
'年龄': 'mean'
}).round(2)
summary.to_excel(writer, sheet_name='汇总')
# 详细信息
details = df.sort_values(['部门', '薪资'], ascending=[True, False])
details.to_excel(writer, sheet_name='详细数据', index=False)
# 交叉分析
cross = pd.crosstab(df['部门'], df['性别'], margins=True)
cross.to_excel(writer, sheet_name='交叉分析')
# 薪资分布
salary_dist = df.groupby(['部门', pd.cut(df['薪资'],
bins=3,
labels=['低', '中', '高'])]).size().unstack()
salary_dist.to_excel(writer, sheet_name='薪资分布')
print(f"报告已导出到:{filename}")
# 导出报告
export_dept_report_to_excel(df)
这些案例涵盖了Pandas数据分组报告的常见应用场景,包括:
- 基础分组统计
- 多级分组
- 分组排名
- 条件统计
- 时间序列分析
- 综合报告生成
- 可视化
- 自定义分组
- 报告导出
根据实际需求,可以组合使用这些技术来生成复杂的分析报告。