本文目录导读:

我来为你介绍如何用Pandas实现数据分组日历的多个实用案例:
案例1:基础日历年月分组统计
import pandas as pd
import numpy as np
from datetime import datetime
# 创建示例数据
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2023-12-31', freq='H')
data = pd.DataFrame({
'日期': dates,
'销售额': np.random.randint(100, 1000, len(dates)),
'用户数': np.random.randint(10, 100, len(dates))
})
# 提取年月信息
data['年'] = data['日期'].dt.year
data['月'] = data['日期'].dt.month
data['年-月'] = data['日期'].dt.strftime('%Y-%m')
# 按月分组统计
monthly_stats = data.groupby('年-月').agg({
'销售额': ['sum', 'mean', 'max'],
'用户数': ['sum', 'mean']
}).round(2)
print("月度统计:")
print(monthly_stats.head())
案例2:按周和季度分组
# 设置日期为索引
data.set_index('日期', inplace=True)
# 按周分组
weekly_stats = data.resample('W').agg({
'销售额': ['sum', 'mean'],
'用户数': 'sum'
})
print("\n周度统计(前5周):")
print(weekly_stats.head())
# 按季度分组
quarterly_stats = data.resample('Q').agg({
'销售额': ['sum', 'mean', 'std'],
'用户数': ['sum', 'mean']
}).round(2)
print("\n季度统计:")
print(quarterly_stats)
案例3:工作日与周末分析
# 创建包含工作日信息的数据
data['星期几'] = data.index.dayofweek
data['是否工作日'] = data['星期几'].apply(lambda x: '工作日' if x < 5 else '周末')
# 按工作日/周末分组
workday_stats = data.groupby('是否工作日').agg({
'销售额': ['sum', 'mean', 'count'],
'用户数': ['sum', 'mean']
}).round(2)
print("\n工作日 vs 周末统计:")
print(workday_stats)
# 按星期几分组
weekday_stats = data.groupby('星期几').agg({
'销售额': ['sum', 'mean'],
'用户数': 'sum'
})
# 重命名星期索引
weekday_names = {0: '周一', 1: '周二', 2: '周三', 3: '周四',
4: '周五', 5: '周六', 6: '周日'}
weekday_stats.index = weekday_stats.index.map(weekday_names)
print("\n每周各天统计:")
print(weekday_stats)
案例4:复杂日历统计(包含节假日)
# 添加节假日信息
holidays_2023 = pd.to_datetime([
'2023-01-01', # 元旦
'2023-01-22', # 春节
'2023-04-05', # 清明节
'2023-05-01', # 劳动节
'2023-06-22', # 端午节
'2023-10-01', # 国庆节
])
data['是否节假日'] = data.index.isin(holidays_2023)
data['日期类型'] = data.apply(lambda row:
'节假日' if row['是否节假日']
else ('周末' if row['星期几'] >= 5 else '工作日'),
axis=1
)
# 按日期类型分组统计
date_type_stats = data.groupby('日期类型').agg({
'销售额': ['sum', 'mean', 'count'],
'用户数': ['sum', 'mean']
}).round(2)
print("\n按日期类型统计:")
print(date_type_stats)
案例5:自定义日历统计函数
def calendar_summary(df, date_col='日期', value_cols=['销售额', '用户数']):
"""
生成完整的日历统计摘要
参数:
- df: DataFrame
- date_col: 日期列名
- value_cols: 需要统计的数值列列表
"""
df = df.copy()
df['日期'] = pd.to_datetime(df[date_col])
# 提取各种时间维度
df['年'] = df['日期'].dt.year
df['月'] = df['日期'].dt.month
df['周'] = df['日期'].dt.isocalendar().week
df['季度'] = df['日期'].dt.quarter
df['星期几'] = df['日期'].dt.dayofweek
df['周几名称'] = df['星期几'].map({
0: '周一', 1: '周二', 2: '周三', 3: '周四',
4: '周五', 5: '周六', 6: '周日'
})
# 生成多种分组统计
summaries = {}
# 1. 年月统计
summaries['year_month'] = df.groupby(['年', '月'])[value_cols].sum()
# 2. 季度统计
summaries['quarterly'] = df.groupby(['年', '季度'])[value_cols].agg(['sum', 'mean'])
# 3. 周统计
summaries['weekly'] = df.groupby(['年', '周'])[value_cols].sum()
# 4. 星期统计
summaries['weekday'] = df.groupby('周几名称')[value_cols].mean()
return summaries
# 使用自定义函数
summaries = calendar_summary(data.reset_index())
print("年月统计:")
print(summaries['year_month'].head(6))
print("\n平均星期统计:")
print(summaries['weekday'])
案例6:可视化日历统计
import matplotlib.pyplot as plt
# 准备数据
data['日期'] = data.index
daily_sales = data.groupby('日期')['销售额'].sum().reset_index()
# 创建日历热力图
def plot_calendar_heatmap(df, date_col, value_col, year=2023):
"""绘制日历热力图"""
# 筛选指定年份
df_year = df[pd.to_datetime(df[date_col]).dt.year == year].copy()
df_year['日期'] = pd.to_datetime(df_year[date_col])
df_year['月'] = df_year['日期'].dt.month
df_year['日'] = df_year['日期'].dt.day
df_year['周几'] = df_year['日期'].dt.dayofweek
# 创建透视表
pivot = df_year.pivot_table(
values=value_col,
index='周几',
columns='月',
aggfunc='sum',
fill_value=0
)
# 绘制热力图
fig, ax = plt.subplots(figsize=(12, 6))
im = ax.imshow(pivot.values, cmap='YlOrRd', aspect='auto')
# 设置标签
ax.set_xticks(range(12))
ax.set_xticklabels(['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月'])
ax.set_yticks(range(7))
ax.set_yticklabels(['周一', '周二', '周三', '周四', '周五', '周六', '周日'])
plt.colorbar(im, label='销售额')
plt.title(f'{year}年日历销售热力图')
plt.tight_layout()
return fig
# 绘制热力图
fig = plot_calendar_heatmap(daily_sales, '日期', '销售额')
plt.show()
案例7:实际业务场景 - 销售分析
# 创建更真实的销售数据
np.random.seed(42)
sales_data = pd.DataFrame({
'订单日期': pd.date_range('2023-01-01', '2023-12-31', freq='D'),
'产品类别': np.random.choice(['电子产品', '服装', '食品', '家居'], 365),
'销售额': np.random.randint(100, 5000, 365),
'订单数量': np.random.randint(1, 20, 365),
'客户ID': np.random.randint(1000, 2000, 365)
})
# 添加时间维度
sales_data['月份'] = pd.to_datetime(sales_data['订单日期']).dt.month
sales_data['季度'] = pd.to_datetime(sales_data['订单日期']).dt.quarter
sales_data['星期'] = pd.to_datetime(sales_data['订单日期']).dt.day_name()
# 1. 按月份和产品类别分析
monthly_category = sales_data.groupby(['月份', '产品类别']).agg({
'销售额': 'sum',
'订单数量': 'sum',
'客户ID': pd.Series.nunique
}).round(2)
print("月度-产品类别分析:")
print(monthly_category.head(12))
# 2. 按季度和星期分析
quarterly_weekday = sales_data.groupby(['季度', '星期']).agg({
'销售额': ['sum', 'mean', 'count'],
'订单数量': 'sum'
}).round(2)
print("\n季度-星期分析:")
print(quarterly_weekday)
# 3. 交叉分析
cross_analysis = pd.crosstab(
sales_data['季度'],
sales_data['产品类别'],
values=sales_data['销售额'],
aggfunc='sum'
).round(2)
print("\n季度-产品类别交叉分析:")
print(cross_analysis)
# 1. 快速查看数据的时间范围
print(f"数据时间范围:{data.index.min()} 到 {data.index.max()}")
# 2. 统计每天的记录数
daily_counts = data.resample('D').size()
print(f"平均每天记录数:{daily_counts.mean():.0f}")
# 3. 找出销售最高的日期
max_sales_date = data.groupby(data.index.date)['销售额'].sum().idxmax()
print(f"销售最高日期:{max_sales_date}")
# 4. 计算同比环比
monthly_sales = data.resample('M')['销售额'].sum()
yoy_growth = monthly_sales.pct_change(periods=12) * 100
mom_growth = monthly_sales.pct_change() * 100
# 5. 创建日期维度表
date_dim = pd.DataFrame({
'日期': pd.date_range('2023-01-01', '2023-12-31'),
'年': range(2023, 2024),
'月': range(1, 13),
'日': range(1, 32)
})
这些案例涵盖了从基础到高级的数据分组日历分析技巧,可以根据实际业务需求灵活运用。