Python案例如何用Pandas做数据分组重构

wen python案例 2

本文目录导读:

Python案例如何用Pandas做数据分组重构

  1. 基础数据准备
  2. 案例一:分组统计与聚合
  3. 案例二:数据透视表
  4. 案例三:分组后的数据重构
  5. 案例四:分组后的自定义处理
  6. 案例五:实际应用场景
  7. 性能优化技巧

我来详细讲解如何使用 Pandas 进行数据分组重构,包括多个实际案例。

基础数据准备

import pandas as pd
import numpy as np
# 创建示例数据
df = pd.DataFrame({
    '日期': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02', '2024-01-03'],
    '产品': ['A', 'B', 'A', 'B', 'A'],
    '城市': ['北京', '上海', '北京', '上海', '北京'],
    '销量': [100, 150, 120, 180, 110],
    '金额': [1000, 1500, 1200, 1800, 1100]
})
print("原始数据:")
print(df)

案例一:分组统计与聚合

1 单列分组统计

# 按产品分组,计算销量总和
product_sum = df.groupby('产品')['销量'].sum()
print("各产品销量总和:")
print(product_sum)
# 按产品分组,计算多列统计量
product_stats = df.groupby('产品').agg({
    '销量': ['sum', 'mean', 'max', 'min'],
    '金额': ['sum', 'mean']
})
print("\n多指标统计:")
print(product_stats)

2 多列分组

# 按产品和城市分组
grouped = df.groupby(['产品', '城市'])['销量'].sum()
print("各产品在各城市的销量:")
print(grouped)
# 使用 reset_index() 转换回 DataFrame
grouped_df = df.groupby(['产品', '城市']).agg({
    '销量': 'sum',
    '金额': 'mean'
}).reset_index()
print("\n重置索引后:")
print(grouped_df)

案例二:数据透视表

1 基本透视表

# 创建透视表
pivot_table = pd.pivot_table(
    df,
    values='销量',
    index='日期',
    columns='产品',
    aggfunc='sum',
    fill_value=0
)
print("销量透视表:")
print(pivot_table)
# 多值透视表
multi_pivot = pd.pivot_table(
    df,
    values=['销量', '金额'],
    index='日期',
    columns='产品',
    aggfunc='sum',
    fill_value=0
)
print("\n多值透视表:")
print(multi_pivot)

2 复杂透视表

# 创建更复杂的数据
df_complex = pd.DataFrame({
    '年份': [2023, 2023, 2023, 2023, 2024, 2024],
    '季度': ['Q1', 'Q2', 'Q1', 'Q2', 'Q1', 'Q2'],
    '产品': ['A', 'A', 'B', 'B', 'A', 'B'],
    '销量': [100, 150, 200, 180, 120, 190],
    '利润': [30, 45, 60, 54, 36, 57]
})
# 多层次透视表
complex_pivot = pd.pivot_table(
    df_complex,
    values='销量',
    index=['年份', '季度'],
    columns='产品',
    aggfunc='sum',
    fill_value=0,
    margins=True,  # 添加汇总行/列
    margins_name='合计'
)
print("多层次透视表(含汇总):")
print(complex_pivot)

案例三:分组后的数据重构

1 stack/unstack 操作

# 先设置索引
df_indexed = df.set_index(['日期', '产品', '城市'])
# unstack - 将索引转为列
unstacked = df_indexed.unstack(level='产品')
print("unstack 转换:")
print(unstacked)
# stack - 将列转为索引
stacked = unstacked.stack(level='产品')
print("\nstack 恢复:")
print(stacked)

2 melt 宽表转长表

# 创建宽表数据
df_wide = pd.DataFrame({
    '日期': ['2024-01-01', '2024-01-02'],
    '产品A销量': [100, 120],
    '产品B销量': [150, 180],
    '产品A金额': [1000, 1200],
    '产品B金额': [1500, 1800]
})
print("宽表数据:")
print(df_wide)
# 转换为长表
df_long = pd.melt(
    df_wide,
    id_vars=['日期'],
    var_name='产品_指标',
    value_name='值'
)
print("\n转换后的长表:")
print(df_long)
# 进一步拆分产品名称和指标
df_long[['产品', '指标']] = df_long['产品_指标'].str.extract(r'产品(.)(.+)')
df_long = df_long.drop('产品_指标', axis=1)
print("\n拆分后的数据:")
print(df_long)

案例四:分组后的自定义处理

1 使用 apply 自定义函数

# 定义自定义聚合函数
def custom_agg(x):
    return pd.Series({
        '总和': x.sum(),
        '均值': x.mean(),
        '标准差': x.std(),
        '变异系数': x.std() / x.mean() if x.mean() != 0 else 0
    })
# 应用自定义函数
custom_result = df.groupby('产品')['销量'].apply(custom_agg)
print("自定义聚合结果:")
print(custom_result)

2 分组排名

# 按产品分组,计算每日销量排名
df['销量排名'] = df.groupby('产品')['销量'].rank(ascending=False)
print("各产品销量排名:")
print(df[['日期', '产品', '销量', '销量排名']])
# 分组计算累计百分比
df['累计销量'] = df.groupby('产品')['销量'].cumsum()
df['累计百分比'] = df.groupby('产品')['销量'].apply(
    lambda x: x.cumsum() / x.sum() * 100
)
print("\n累计分析:")
print(df[['日期', '产品', '销量', '累计销量', '累计百分比']])

案例五:实际应用场景

1 销售数据分析

# 模拟销售数据
np.random.seed(42)
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(1, 30, 100),
    '单价': np.random.choice([2999, 3999, 4999, 5999], 100)
})
sales_data['销售额'] = sales_data['销量'] * sales_data['单价']
# 月度门店销售汇总
sales_data['月份'] = sales_data['日期'].dt.month
monthly_store = pd.pivot_table(
    sales_data,
    values=['销量', '销售额'],
    index='月份',
    columns='门店',
    aggfunc='sum',
    fill_value=0
)
print("月度门店销售汇总:")
print(monthly_store)
# 产品销量排行
product_rank = sales_data.groupby('产品').agg({
    '销量': 'sum',
    '销售额': 'sum',
    '门店': lambda x: x.nunique()
}).rename(columns={'门店': '门店数量'})
product_rank['销量占比'] = product_rank['销量'] / product_rank['销量'].sum() * 100
product_rank = product_rank.sort_values('销售额', ascending=False)
print("\n产品销售排行:")
print(product_rank)

2 库存分析

# 创建库存数据
inventory_data = pd.DataFrame({
    '产品': ['A', 'A', 'B', 'B', 'C', 'C'],
    '仓库': ['北京仓', '上海仓', '北京仓', '上海仓', '北京仓', '上海仓'],
    '入库量': [100, 150, 200, 180, 120, 90],
    '出库量': [50, 80, 120, 100, 60, 40],
    '安全库存': [80, 100, 120, 100, 60, 50]
})
# 计算库存状态
inventory_data['当前库存'] = inventory_data['入库量'] - inventory_data['出库量']
inventory_data['库存状态'] = inventory_data.apply(
    lambda row: '正常' if row['当前库存'] >= row['安全库存'] else '补货', 
    axis=1
)
# 按产品和仓库分组
inventory_summary = inventory_data.groupby(['产品', '仓库']).agg({
    '当前库存': 'sum',
    '安全库存': 'sum',
    '入库量': 'sum'
}).reset_index()
inventory_summary['补货建议'] = inventory_summary['安全库存'] - inventory_summary['当前库存']
inventory_summary['补货建议'] = inventory_summary['补货建议'].clip(lower=0)
print("库存分析结果:")
print(inventory_summary)

性能优化技巧

# 大数据集处理优化
def optimized_groupby(df, group_cols, agg_dict):
    """
    优化分组聚合性能
    """
    # 使用分类数据类型
    for col in group_cols:
        if df[col].dtype == 'object':
            df[col] = df[col].astype('category')
    # 使用 transform 代替 apply
    result = df.groupby(group_cols, observed=True).agg(agg_dict)
    return result
# 使用示例
df_optimized = df.copy()
result = optimized_groupby(
    df_optimized, 
    ['产品'], 
    {'销量': 'sum', '金额': 'mean'}
)
print("优化后的分组结果:")
print(result)

这些案例涵盖了 Pandas 数据分组重构的主要场景,核心要点:

  1. groupby + agg:最常用的分组聚合方式
  2. pivot_table:创建透视表进行多维度分析
  3. stack/unstack:行列转换
  4. melt:宽表转长表
  5. 自定义函数:处理复杂的分组逻辑

根据实际需求选择合适的重构方法,可以提高数据分析效率。

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