本文目录导读:

我来详细介绍Pandas数据分组伸缩的常见案例和操作方法。
基础数据准备
import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
'部门': ['销售部', '销售部', '技术部', '技术部', '市场部', '市场部'],
'区域': ['华东', '华北', '华东', '华北', '华东', '华北'],
'销售员': ['张三', '李四', '王五', '赵六', '钱七', '孙八'],
'销售额': [10000, 15000, 12000, 18000, 9000, 11000],
'数量': [50, 75, 60, 90, 45, 55],
'日期': ['2024-01', '2024-01', '2024-02', '2024-02', '2024-01', '2024-02']
})
print("原始数据:")
print(df)
基础分组操作
单列分组聚合
# 按部门分组,计算销售额总和
dept_sales = df.groupby('部门')['销售额'].sum()
print("各部门销售总额:")
print(dept_sales)
# 按部门分组,多列聚合
dept_stats = df.groupby('部门').agg({
'销售额': ['sum', 'mean', 'max', 'min'],
'数量': ['sum', 'mean']
})
print("\n各部门统计:")
print(dept_stats)
多列分组
# 按部门和区域分组
dept_region = df.groupby(['部门', '区域'])['销售额'].sum()
print("各部门各区域销售额:")
print(dept_region)
常见聚合函数用法
# 多种聚合方式
result = df.groupby('部门').agg(
总销售额=('销售额', 'sum'),
平均销售额=('销售额', 'mean'),
最大销售额=('销售额', 'max'),
销售次数=('销售额', 'count'),
销售员列表=('销售员', lambda x: ', '.join(x))
)
print("综合统计:")
print(result)
数据伸缩(变换)操作
transform(保持原行数)
# 计算每个部门销售额占比
df['部门销售额占比'] = df.groupby('部门')['销售额'].transform(
lambda x: x / x.sum() * 100
)
# 计算每个部门内的排名
df['部门内排名'] = df.groupby('部门')['销售额'].rank(ascending=False)
print("添加计算列后的数据:")
print(df[['部门', '销售员', '销售额', '部门销售额占比', '部门内排名']])
标准化处理
# Z-score标准化(按组)
df['销售额_zscore'] = df.groupby('部门')['销售额'].transform(
lambda x: (x - x.mean()) / x.std()
)
# Min-Max标准化(按组)
df['销售额_minmax'] = df.groupby('部门')['销售额'].transform(
lambda x: (x - x.min()) / (x.max() - x.min())
)
print("标准化后的数据:")
print(df[['部门', '销售员', '销售额', '销售额_zscore', '销售额_minmax']])
高级分组操作
自定义聚合函数
def custom_agg(x):
"""自定义聚合函数"""
return {
'数量': x.sum(),
'avg_price': (x['销售额'].sum() / x['数量'].sum()).round(2),
'top_seller': x.loc[x['销售额'].idxmax(), '销售员']
}
# 应用自定义函数
result = df.groupby('部门').apply(custom_agg)
print("自定义聚合结果:")
print(result)
分组后的过滤
# 找出销售额大于平均水平的记录
above_avg = df.groupby('部门').filter(
lambda x: x['销售额'].mean() > 13000
)
print("高于平均水平的记录:")
print(above_avg)
# 保留销售额最高的前2条记录
top2 = df.groupby('部门').apply(
lambda x: x.nlargest(2, '销售额')
).reset_index(drop=True)
print("\n各部门Top2销售记录:")
print(top2)
实际应用案例
销售数据分析
# 创建更完整的销售数据
sales_data = 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(500, 5000, 100)
})
# 月度销售汇总
sales_data['月份'] = sales_data['日期'].dt.month
monthly_summary = sales_data.groupby(['月份', '产品']).agg(
总销售额=('销售额', 'sum'),
总成本=('成本', 'sum'),
销售次数=('销售额', 'count'),
平均利润率=('销售额', lambda x: ((x.sum() - sales_data.loc[x.index, '成本'].sum()) / x.sum() * 100).round(2))
).reset_index()
print("月度销售汇总:")
print(monthly_summary)
# 按区域和产品计算占比
sales_data['区域销售占比'] = sales_data.groupby('区域')['销售额'].transform(
lambda x: x / x.sum() * 100
)
# 动态滚动统计(组内)
sales_data['区域累计销售额'] = sales_data.groupby('区域')['销售额'].transform(
lambda x: x.expanding().sum()
)
薪资数据分析
# 员工薪资数据
salary_df = pd.DataFrame({
'部门': ['技术']*6 + ['销售']*6 + ['人事']*6,
'职级': ['初级', '中级', '高级']*6,
'薪资': np.random.randint(5000, 30000, 18)
})
# 各部门薪资统计
salary_stats = salary_df.groupby(['部门', '职级']).agg(
平均薪资=('薪资', 'mean'),
最高薪资=('薪资', 'max'),
最低薪资=('薪资', 'min'),
薪资中位数=('薪资', 'median')
).round(0)
# 添加部门排名
salary_df['部门薪资排名'] = salary_df.groupby('部门')['薪资'].rank(ascending=False)
# 计算薪资与部门平均的差距
salary_df['与部门平均差距'] = salary_df['薪资'] - salary_df.groupby('部门')['薪资'].transform('mean')
print("薪资分析结果:")
print(salary_stats)
print("\n详细薪资数据:")
print(salary_df)
性能优化技巧
import time
# 大数据集测试
large_df = pd.DataFrame({
'group': np.random.choice(list('ABCDE'), 100000),
'value': np.random.randn(100000)
})
# 方法1:直接groupby
start = time.time()
result1 = large_df.groupby('group')['value'].sum()
print(f"直接groupby耗时: {time.time() - start:.4f}秒")
# 方法2:使用categorical类型优化
large_df['group'] = large_df['group'].astype('category')
start = time.time()
result2 = large_df.groupby('group', observed=True)['value'].sum()
print(f"优化后耗时: {time.time() - start:.4f}秒")
# 方法3:多个聚合同时进行
start = time.time()
result3 = large_df.groupby('group')['value'].agg(['sum', 'mean', 'std'])
print(f"多聚合耗时: {time.time() - start:.4f}秒")
# 1. 重置索引
result = df.groupby('部门')['销售额'].sum().reset_index()
# 2. 多重索引处理
result = df.groupby(['部门', '区域'])['销售额'].sum().unstack()
# 3. 条件分组
df['业绩等级'] = pd.cut(df['销售额'],
bins=[0, 10000, 15000, float('inf')],
labels=['低', '中', '高']
)
# 4. 分组后合并
group_keys = list(df.groupby('部门').groups.keys())
# 5. 自定义分组键
df['分组'] = df.apply(
lambda row: '高绩效' if row['销售额'] > row['数量'] * 200 else '普通',
axis=1
)
这些案例涵盖了Pandas分组伸缩的常用操作,从基础到高级应用都有涉及,根据实际需求,你可以灵活组合这些方法来解决数据分析中的各种问题。