Python案例怎么实现数据分组?

wen python案例 11

Python案例:5种高效数据分组实现方法详解(附代码)

目录导读

Python案例怎么实现数据分组?

  1. 数据分组的核心概念与场景
  2. 基础方法:用Pandas的groupby实现分组统计
  3. 高级技巧:自定义分组函数与多级分组
  4. 实战案例:电商订单数据按用户ID分组分析
  5. 分组后聚合、转换与过滤的完整流程
  6. 常见问题QA(含性能优化建议)

数据分组的核心概念与场景

数据分组是数据分析中最重要的操作之一,它允许我们按照特定维度(如时间、类别、用户ID)将数据划分为若干子集,然后对每个子集执行统计、转换或过滤操作,在电商场景中,我们需要按用户ID汇总订单金额;在金融场景中,需按股票代码计算每日收益率。

Python中实现数据分组主要依赖pandas库,它提供了groupby()方法,底层基于Cython优化,能够高效处理百万级数据,但很多初学者只会基础的按单列分组求和,遇到复合条件或性能瓶颈时就会束手无策,本文将通过5个真实案例,系统讲解从基础到进阶的Python数据分组实现技巧。


基础方法:用Pandas的groupby实现分组统计

案例1:单列分组聚合
假设我们有一个销售数据表sales.csv,包含region(区域)、amount(销售额)、date(日期)三列。

import pandas as pd
df = pd.read_csv('sales.csv')
# 按区域分组,计算销售额总和
grouped = df.groupby('region')['amount'].sum()
print(grouped)

案例2:多列分组
按区域和季度同时分组:

df['quarter'] = pd.to_datetime(df['date']).dt.quarter
result = df.groupby(['region', 'quarter'])['amount'].agg(['sum', 'mean', 'count'])

核心知识点

  • groupby后的列选择:['amount'][['amount']](返回DataFrame vs Series)
  • 聚合函数:sum()mean()std()count()
  • agg()方法支持同时计算多个指标,如agg(['sum','max'])

高级技巧:自定义分组函数与多级分组

当内置函数无法满足需求时,可以使用apply()transform(),例如需要每个组内的销售金额排名:

# 按区域分组,给每个区域内的销售额排名
df['rank_in_region'] = df.groupby('region')['amount'].rank(ascending=False)

自定义分组规则
按某个条件的逻辑值分组,比如将amount分成高、中、低三档:

def amount_category(amount):
    if amount > 1000:
        return 'high'
    elif amount > 500:
        return 'medium'
    else:
        return 'low'
df['category'] = df['amount'].apply(amount_category)
grouped = df.groupby('category')['amount'].mean()

性能提示:自定义函数使用apply会逐行执行,效率较低,建议先通过cut()qcut()分箱,再直接用列名分组。


实战案例:电商订单数据按用户ID分组分析

数据说明:用户订单表包含user_id(用户ID)、order_amount(订单金额)、order_date(下单时间)、product_category(商品类别)。

需求:计算每个用户的:

  • 总消费金额
  • 下单次数
  • 最近一次下单时间
  • 最高单笔订单金额

实现代码

# 加载数据
orders = pd.read_csv('orders.csv')
# 分组计算统计
user_stats = orders.groupby('user_id').agg({
    'order_amount': ['sum', 'max', 'count'],
    'order_date': 'max'
})
# 重命名列
user_stats.columns = ['total_spent', 'max_order', 'order_count', 'last_order_date']
user_stats = user_stats.reset_index()

扩展分析:找出高价值用户(总消费前10%且最近30天有消费):

import datetime as dt
today = dt.date.today()
user_stats['recency'] = (today - pd.to_datetime(user_stats['last_order_date']).dt.date).dt.days
high_value = user_stats[user_stats['total_spent'] > user_stats['total_spent'].quantile(0.9)]
active_high = high_value[high_value['recency'] <= 30]

分组后聚合、转换与过滤的完整流程

三种核心操作对比

操作 说明 返回值长度 常用方法
聚合(Aggregation) 每个组汇总成一个值 组数 agg(), sum()
转换(Transformation) 每组内部处理,保留原形状 原Rows数 transform()
过滤(Filteration) 根据组属性筛选组 部分Rows filter()

转换应用:填充组内缺失值:

# 按区域分组,用区域均值填充缺失金额
df['amount_filled'] = df.groupby('region')['amount'].transform(lambda x: x.fillna(x.mean()))

过滤应用:只保留订单数超过10次的用户:

def keep_high_freq(group):
    return group[group['user_id'].count() > 10]
filtered = orders.groupby('user_id').filter(lambda g: len(g) > 10)

常见问题QA(含性能优化建议)

Q1:分组后内存溢出怎么办?
A:使用dask库进行分布式处理,或者按时间分块处理:

for chunk in pd.read_csv('big_data.csv', chunksize=10000):
    chunk.groupby('key').agg(...).to_csv('tmp.csv', mode='a')

Q2:为什么groupby后索引混乱?
A:groupby默认将分组键设为索引,使用as_index=False可保留原始索引:

df.groupby('region', as_index=False)['amount'].sum()

Q3:如何提高groupby速度?
A:

  • 使用categorical类型存储分组键:df['region'] = df['region'].astype('category')
  • 避免使用apply,优先用aggtransform的内置方法
  • 使用numba加速自定义函数,或直接使用pandaseval()

Q4:多级索引怎么访问?
A:使用xs()方法:grouped.xs('2024-01', level='date')

Q5:分组后如何保留非聚合列?
A:使用first()last()

df.groupby('user_id').agg({
    'order_amount': 'sum',
    'product_category': 'first'  # 保留分组后的第一个产品类别
})

通过以上案例,相信你已经掌握了Python数据分组的核心实现方法,从基础的groupby聚合到复杂的自定义分组、多级索引处理,再到实战中的用户行为分析,这些技巧能覆盖90%以上的数据分析场景,建议你在真实数据集中动手实践,特别是结合pandaspivot_tablecrosstab两个姊妹函数,可以更高效地完成数据分组任务,如果遇到具体问题,欢迎在文档中搜索相关函数参数,或参考官方API文档(pandas.pydata.org)——搜索引擎是最好的老师,但实践才是掌握的关键。

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