11.13 Pandas进阶:掌握多级分组与高级聚合,解锁数据分析新维度


文章目录


前言

在数据分析的世界里,简单的一维分组统计往往无法满足我们对数据洞察的深度需求。今天,让我们一起探索Pandas中多级分组和高级聚合的强大功能,让你的数据分析能力更上一层楼!


一、多级分组:层层深入的数据洞察

多级分组就像是数据版的俄罗斯套娃,每一层都揭示着不同的信息维度。

基础多级分组操作

python 复制代码
python
import pandas as pd
import numpy as np

# 创建示例销售数据
np.random.seed(42)
data = {
    '年份': np.random.choice([2021, 2022, 2023], 100),
    '季度': np.random.choice(['Q1', 'Q2', 'Q3', 'Q4'], 100),
    '地区': np.random.choice(['华东', '华南', '华北', '西部'], 100),
    '产品类别': np.random.choice(['电子产品', '服装', '食品', '家居'], 100),
    '销售额': np.random.uniform(1000, 50000, 100).round(2),
    '销量': np.random.randint(10, 500, 100)
}

df = pd.DataFrame(data)
print("原始数据样例:")
print(df.head())
print(f"\n数据形状:{df.shape}")

# 简单的单级分组
region_sales = df.groupby('地区')['销售额'].sum()
print("\n按地区分组销售额:")
print(region_sales)

# 多级分组:地区 + 产品类别
multi_group = df.groupby(['地区', '产品类别'])['销售额'].sum()
print("\n按地区和产品类别分组:")
print(multi_group)

多级分组索引操作

python 复制代码
python
# 创建多级分组对象
grouped = df.groupby(['年份', '季度', '地区'])

# 查看分组结构
print("分组数量:", grouped.ngroups)
print("分组键示例:", list(grouped.groups.keys())[:5])

# 选择特定分组的数据
specific_group = grouped.get_group((2022, 'Q2', '华东'))
print("\n2022年Q2华东地区数据:")
print(specific_group.head())

# 多级索引的切片操作
multi_index_result = df.groupby(['年份', '季度'])['销售额'].sum()
print("\n按年份和季度分组的销售额:")
print(multi_index_result)

# 使用unstack转换格式
pivot_result = multi_index_result.unstack()
print("\n数据透视格式:")
print(pivot_result)

# 交换索引层级
swapped = multi_index_result.swaplevel()
print("\n交换层级后的结果:")
print(swapped.head())

二、高级聚合:多维度统计的艺术

单一聚合函数已经不能满足需求?来看看高级聚合能做什么!

多指标聚合

python 复制代码
python
# 同时对多个列应用多个聚合函数
advanced_agg = df.groupby(['地区', '产品类别']).agg({
    '销售额': ['sum', 'mean', 'std', 'max', 'min'],
    '销量': ['sum', 'mean', 'count']
}).round(2)

print("多指标聚合结果:")
print(advanced_agg)

# 自定义列名
custom_agg = df.groupby(['地区', '产品类别']).agg(
    总销售额=('销售额', 'sum'),
    平均销售额=('销售额', 'mean'),
    销售额标准差=('销售额', 'std'),
    最高销售额=('销售额', 'max'),
    总销量=('销量', 'sum'),
    订单数量=('销量', 'count')
).round(2)

print("\n自定义列名的聚合结果:")
print(custom_agg)

条件聚合

python 复制代码
python
# 定义条件聚合函数
def high_sales_mean(df):
    """只计算高销售额(大于平均值)的平均值"""
    high_sales = df[df['销售额'] > df['销售额'].mean()]
    return high_sales['销售额'].mean()

def sales_distribution(df):
    """计算销售额分布:低/中/高"""
    q1 = df['销售额'].quantile(0.25)
    q3 = df['销售额'].quantile(0.75)
    
    low = (df['销售额'] < q1).sum()
    medium = ((df['销售额'] >= q1) & (df['销售额'] <= q3)).sum()
    high = (df['销售额'] > q3).sum()
    
    return pd.Series({'低销售额': low, '中销售额': medium, '高销售额': high})

# 应用条件聚合
conditional_result = df.groupby(['地区']).apply(
    lambda x: pd.Series({
        '高销售额平均值': high_sales_mean(x),
        '总销售额': x['销售额'].sum(),
        '高销售额占比': (x['销售额'] > x['销售额'].mean()).mean() * 100
    })
).round(2)

print("条件聚合结果:")
print(conditional_result)

三、复杂分组场景实战

场景一:时间序列+多维度分组

python 复制代码
python
# 创建时间序列数据
dates = pd.date_range('2023-01-01', periods=365, freq='D')
time_series_data = pd.DataFrame({
    '日期': np.random.choice(dates, 1000),
    '城市': np.random.choice(['北京', '上海', '广州', '深圳'], 1000),
    '产品线': np.random.choice(['手机', '电脑', '平板', '配件'], 1000),
    '销售额': np.random.uniform(100, 10000, 1000).round(2),
    '利润率': np.random.uniform(0.1, 0.5, 1000)
})

# 添加时间维度列
time_series_data['月份'] = time_series_data['日期'].dt.month
time_series_data['季度'] = time_series_data['日期'].dt.quarter
time_series_data['星期几'] = time_series_data['日期'].dt.day_name()

# 多层时间+维度分组
time_grouped = time_series_data.groupby(
    ['城市', time_series_data['日期'].dt.to_period('M'), '产品线']
)

# 复杂聚合计算
time_analysis = time_grouped.agg({
    '销售额': ['sum', 'mean', 'count'],
    '利润率': lambda x: (x.mean() * 100).round(2)
}).round(2)

print("时间序列多维度分析:")
print(time_analysis.head(10))

场景二:跨维度计算指标

python 复制代码
python
# 计算每个地区-产品类别的市场份额
total_sales_by_region = df.groupby('地区')['销售额'].sum()
total_sales_by_category = df.groupby('产品类别')['销售额'].sum()

# 方法1:使用transform计算组内占比
df['地区内占比'] = df.groupby('地区')['销售额'].transform(
    lambda x: x / x.sum() * 100
).round(2)

df['类别内占比'] = df.groupby('产品类别')['销售额'].transform(
    lambda x: x / x.sum() * 100
).round(2)

# 方法2:计算跨维度指标
market_share = df.groupby(['地区', '产品类别']).agg({
    '销售额': 'sum'
}).groupby(level=0).transform(
    lambda x: x / x.sum() * 100
).round(2)

market_share.columns = ['地区市场份额']
market_share = market_share.reset_index()

print("\n市场份额分析:")
print(market_share.head(10))

# 方法3:使用pivot_table计算
pivot_market = pd.pivot_table(
    df,
    values='销售额',
    index='地区',
    columns='产品类别',
    aggfunc='sum',
    margins=True,
    margins_name='总计'
)

# 计算行百分比
row_percentage = pivot_market.div(pivot_market.iloc[:, -1], axis=0) * 100
print("\n各产品在各地区的销售占比:")
print(row_percentage.round(2))

四、高级技巧:自定义聚合与复杂计算

技巧1:链式聚合

python 复制代码
python
# 链式聚合:先分组计算,再对结果进行二次计算
def analyze_sales_trend(group):
    """分析销售趋势"""
    if len(group) < 2:
        return pd.Series({
            '增长趋势': '数据不足',
            '月均增长率': 0,
            '稳定性': 0
        })
    
    # 按月份排序
    sorted_group = group.sort_values('月份')
    
    # 计算增长率
    growth_rates = sorted_group['销售额'].pct_change().dropna()
    
    # 判断趋势
    if growth_rates.mean() > 0.1:
        trend = '快速增长'
    elif growth_rates.mean() > 0:
        trend = '缓慢增长'
    elif growth_rates.mean() < -0.1:
        trend = '快速下降'
    else:
        trend = '稳定'
    
    return pd.Series({
        '增长趋势': trend,
        '月均增长率': growth_rates.mean() * 100,
        '稳定性': 1 - growth_rates.std(),
        '数据点数': len(group)
    })

# 应用链式聚合
chain_analysis = time_series_data.groupby(['城市', '产品线']).apply(analyze_sales_trend)
print("\n销售趋势分析:")
print(chain_analysis.head(10))

技巧2:递归分组分析

python 复制代码
python
def recursive_group_analysis(df, group_cols, depth=0, max_depth=2):
    """递归分组分析函数"""
    if depth >= max_depth or not group_cols:
        return df['销售额'].describe()
    
    current_col = group_cols[0]
    remaining_cols = group_cols[1:]
    
    results = {}
    for group_name, group_data in df.groupby(current_col):
        if depth == max_depth - 1:
            results[group_name] = group_data['销售额'].describe()
        else:
            results[group_name] = recursive_group_analysis(
                group_data, remaining_cols, depth + 1, max_depth
            )
    
    return pd.concat(results, names=[current_col])

# 递归分析示例
recursive_result = recursive_group_analysis(
    df, 
    group_cols=['地区', '产品类别', '年份'],
    max_depth=2
)

print("\n递归分组分析结果:")
print(recursive_result.head(20))

五、性能优化与最佳实践

性能优化技巧

python 复制代码
python
# 技巧1:使用named aggregation(性能更好)
fast_agg = df.groupby(['地区', '产品类别']).agg(
    总销售额=pd.NamedAgg(column='销售额', aggfunc='sum'),
    平均销售额=pd.NamedAgg(column='销售额', aggfunc='mean'),
    销售数量=pd.NamedAgg(column='销量', aggfunc='sum')
)

# 技巧2:预过滤数据
# 错误做法:分组后过滤
# 正确做法:先过滤再分组
high_value_data = df[df['销售额'] > df['销售额'].quantile(0.75)]
grouped_high = high_value_data.groupby(['地区', '产品类别']).agg({'销售额': 'sum'})

# 技巧3:使用categorical类型加速分组
df['地区'] = df['地区'].astype('category')
df['产品类别'] = df['产品类别'].astype('category')

# 重新分组(会更快)
optimized_grouping = df.groupby(['地区', '产品类别']).agg({'销售额': 'sum'})

实用函数封装

python 复制代码
python
def smart_group_analysis(df, group_columns, value_column, 
                         agg_funcs=None, top_n=None):
    """
    智能分组分析函数
    
    参数:
    - df: 数据框
    - group_columns: 分组列列表
    - value_column: 分析值列
    - agg_funcs: 聚合函数字典,默认包含常用统计量
    - top_n: 只显示前N个分组
    """
    if agg_funcs is None:
        agg_funcs = {
            '总和': 'sum',
            '平均值': 'mean',
            '标准差': 'std',
            '最小值': 'min',
            '最大值': 'max',
            '中位数': 'median',
            '计数': 'count'
        }
    
    # 执行分组聚合
    result = df.groupby(group_columns)[value_column].agg(agg_funcs)
    
    # 如果需要,筛选前N个
    if top_n and len(group_columns) == 1:
        total_by_group = df.groupby(group_columns[0])[value_column].sum()
        top_groups = total_by_group.nlargest(top_n).index
        result = result.loc[top_groups]
    
    return result.round(2)

# 使用封装函数
quick_analysis = smart_group_analysis(
    df=df,
    group_columns=['地区', '产品类别'],
    value_column='销售额',
    top_n=5
)

print("\n智能分组分析结果:")
print(quick_analysis.head(10))

六、真实业务场景应用

电商销售漏斗分析

python 复制代码
python
# 模拟电商数据
ecommerce_data = pd.DataFrame({
    'user_id': np.arange(1, 1001),
    '注册日期': pd.date_range('2023-01-01', periods=1000, freq='D'),
    '用户层级': np.random.choice(['新用户', '活跃用户', '核心用户', '流失用户'], 1000, p=[0.3, 0.4, 0.2, 0.1]),
    '所在城市': np.random.choice(['一线城市', '二线城市', '三线及以下'], 1000),
    '最近购买月份': pd.to_datetime(np.random.choice(
        pd.date_range('2023-01-01', '2023-12-01', freq='M'), 1000
    )),
    '购买金额': np.random.exponential(500, 1000).round(2),
    '购买次数': np.random.poisson(3, 1000)
})

# 添加月份信息
ecommerce_data['注册月份'] = ecommerce_data['注册日期'].dt.to_period('M')
ecommerce_data['最近购买月份'] = ecommerce_data['最近购买月份'].dt.to_period('M')

# 复杂的分层分组分析
funnel_analysis = ecommerce_data.groupby(
    ['注册月份', '用户层级', '所在城市']
).agg({
    'user_id': 'count',
    '购买金额': ['sum', 'mean'],
    '购买次数': ['sum', 'mean']
}).round(2)

# 计算用户留存率
cohort_analysis = ecommerce_data.pivot_table(
    index='注册月份',
    columns=ecommerce_data['最近购买月份'] - ecommerce_data['注册月份'],
    values='user_id',
    aggfunc='count'
).fillna(0)

print("\n电商用户漏斗分析:")
print(funnel_analysis.head(15))

总结

  1. 通过本文的学习,你应该已经掌握了Pandas多级分组和高级聚合的核心技能:
    多级分组让你能够从多个维度深入分析数据
    高级聚合提供了丰富的统计方法和自定义能力
    性能优化确保分析效率
    实用封装提高代码复用性
  2. 记住这些最佳实践:
    合理使用多级索引和unstack进行数据重塑
    优先使用内置聚合函数,必要时再使用自定义函数
    对分类数据使用categorical类型提升性能
    封装常用分析模式为可重用函数
    多级分组和高级聚合不仅是技术工具,更是数据思维的体现。它们帮助你发现数据中的模式、趋势和异常,为业务决策提供有力支持。
相关推荐
YangYang9YangYan2 小时前
2026高职大数据与会计专业学数据分析的价值分析
大数据·数据挖掘·数据分析
一只小H呀の2 小时前
pandas处理excel数据
excel·pandas
UR的出不克2 小时前
Python实现SMZDM数据处理系统:从爬虫到数据分析的完整实践
爬虫·python·数据分析
瑞华丽PLM3 小时前
工业大数据背景下的PLM数据分析:驱动产品创新新范式
大数据·数据挖掘·数据分析·plm·国产plm·瑞华丽plm·瑞华丽
2501_941333103 小时前
YOLO11-BiFPN实现:小麦杂质检测与分类系统详解_1
人工智能·分类·数据挖掘
STLearner3 小时前
AAAI 2026 | 时间序列(Time Series) 论文总结[下] (分类,异常检测,基础模型,表示学习,生成)
大数据·论文阅读·人工智能·python·深度学习·机器学习·数据挖掘
大闲在人4 小时前
22. EOQ 扩展模型:有限生产率场景下的库存优化
数据分析·供应链管理·智能制造·库存管理·工业工程
YangYang9YangYan4 小时前
2026大专财务专业学数据分析的价值分析
数据挖掘·数据分析
2501_941507945 小时前
【珠宝识别】使用YOLOv8-HSFPN实现首饰分类检测系统详解
yolo·分类·数据挖掘