本文目录导读:

我来详细讲解如何使用 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 数据分组重构的主要场景,核心要点:
- groupby + agg:最常用的分组聚合方式
- pivot_table:创建透视表进行多维度分析
- stack/unstack:行列转换
- melt:宽表转长表
- 自定义函数:处理复杂的分组逻辑
根据实际需求选择合适的重构方法,可以提高数据分析效率。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播