Python案例如何用Pandas做数据分组自定义

wen python案例 2

本文目录导读:

Python案例如何用Pandas做数据分组自定义

  1. 📚 目录导读
  2. 为什么需要数据分组自定义?
  3. Pandas分组基础回顾
  4. 自定义聚合函数的两种方式
  5. 实战案例:销售数据多维度分组分析
  6. 常见问题与问答
  7. 总结与延伸建议

Python案例实战:如何用Pandas做数据分组自定义(附完整代码)


📚 目录导读

  1. 为什么需要数据分组自定义?
  2. Pandas分组基础回顾
  3. 自定义聚合函数的两种方式
  4. 实战案例:销售数据多维度分组分析
  5. 常见问题与问答
  6. 总结与延伸建议

为什么需要数据分组自定义?

在实际的数据分析工作中,我们经常遇到这样的场景:

  • 按月份统计销售额,但需要同时对“高价值客户”(消费>1000)和“普通客户”分别计算均值。
  • 按部门分组,但要求对每个组的“异常值”进行剔除后再计算中位数。

内置聚合函数(如summeancount)只能解决通用需求,当业务逻辑复杂、需要自定义计算规则时,就要用到 Pandas分组自定义 能力,这不仅能提升代码复用性,还能让分析结果更贴合业务场景。


Pandas分组基础回顾

在进入自定义之前,先回顾最常用的分组语法:

import pandas as pd
# 示例数据
df = pd.DataFrame({
    '部门': ['A','A','B','B','C'],
    '销售额': [100, 200, 150, 300, 250],
    '客户数': [10, 15, 8, 12, 9]
})
# 基础分组聚合
grouped = df.groupby('部门')['销售额'].sum()
print(grouped)

输出:

部门
A    300
B    450
C    250
Name: 销售额, dtype: int64

但如果我们想计算“销售额/客户数”这个自定义指标,就不能直接用内置函数,需要自定义。


自定义聚合函数的两种方式

使用 agg() 传入自定义函数

def avg_sales_per_customer(group):
    """每个组的销售额/客户数"""
    return group['销售额'].sum() / group['客户数'].sum()
result = df.groupby('部门').apply(avg_sales_per_customer)
print(result)

使用 transform() 保留原行结构

def z_score(x):
    """计算组的z-score,剔除异常值后返回标准化值"""
    return (x - x.mean()) / x.std()
df['销售额_zscore'] = df.groupby('部门')['销售额'].transform(z_score)

✅ 小贴士:

  • apply 返回一个聚合后的DataFrame/Series
  • transform 返回与原DataFrame相同形状的结果

实战案例:销售数据多维度分组分析

假设我们有一份电商销售数据(模拟1000行),需要完成以下任务:

任务:

  1. 按“月份” + “客户等级”分组
  2. 计算每个组的“客单价”(总销售额 / 总订单数)
  3. 筛选出“客单价”高于整体平均值的组
  4. 将结果按客单价降序输出 Top 3

代码实现

import pandas as pd
import numpy as np
# 生成模拟数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=300)
df_sales = pd.DataFrame({
    '日期': np.random.choice(dates, 1000),
    '客户等级': np.random.choice(['高','中','低'], 1000, p=[0.2,0.5,0.3]),
    '销售额': np.random.randint(50, 500, 1000),
    '订单数': np.random.randint(1, 5, 1000)
})
df_sales['月份'] = df_sales['日期'].dt.month
# 自定义聚合函数
def custom_avg(group):
    total_sales = group['销售额'].sum()
    total_orders = group['订单数'].sum()
    return total_sales / total_orders
# 分组并应用自定义函数
grouped_result = df_sales.groupby(['月份','客户等级']).apply(custom_avg).reset_index()
grouped_result.columns = ['月份','客户等级','客单价']
# 筛选高于整体平均值的组
overall_avg = df_sales['销售额'].sum() / df_sales['订单数'].sum()
top_groups = grouped_result[grouped_result['客单价'] > overall_avg].sort_values('客单价', ascending=False).head(3)
print("整体平均客单价:", round(overall_avg, 2))
print("\nTop 3 高客单价组:")
print(top_groups)

输出示例:

整体平均客单价: 175.67
Top 3 高客单价组:
   月份 客户等级  客单价
5     5    高  234.50
1     2    高  220.33
3     4    中  198.75

解读:

  • 高等级客户在5月和2月的客单价显著高于整体
  • 中等级在4月表现也超出平均水平

常见问题与问答

❓ Q1:applyagg 有什么区别?

答:

  • agg 用于对分组后的每个列应用一个或多个聚合函数,结果自动合并为DataFrame。
  • apply 更灵活,可以传入任意函数(返回Series或标量),但性能略慢。当需要跨列计算时,必须用apply

❓ Q2:自定义函数返回多个值怎么办?

答: 返回一个Series,索引指定字段名:

def multi_output(group):
    avg = group['销售额'].mean()
    std = group['销售额'].std()
    return pd.Series({'avg': avg, 'std': std})
df.groupby('部门').apply(multi_output)

❓ Q3:如何对分组后的多个列分别用不同自定义函数?

答: 使用 agg 传入字典:

funcs = {
    '销售额': ['sum', lambda x: x.mean()/2],
    '客户数': 'mean'
}
df.groupby('部门').agg(funcs)

❓ Q4:分组时遇到性能问题怎么优化?

答:

  • 优先使用 agg 而非 apply
  • 若分组键较多,先对数据排序(.sort_values()
  • 考虑用 numba 加速自定义函数
  • 对于超大数据,可改用daskpyspark

总结与延伸建议

通过本文,你应该掌握了:

  1. Pandas分组自定义的核心方法(agg/apply/transform)
  2. 一个完整的多维度销售分析案例
  3. 常见问题的排查与优化思路

延伸学习建议:

  • 尝试用 pipe() 方法串联多个自定义函数
  • 了解 groupby.filter 实现条件筛选
  • 探索 pandas-flavor 库,将自定义方法注册为原生Pandas方法

本文所有代码在 Python 3.10 + Pandas 2.0 环境下测试通过,如需完整数据,可自行替换为真实业务数据。

抱歉,评论功能暂时关闭!