本文目录导读:

我来详细讲解如何使用Pandas进行数据分组和时序分析。
基础准备
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# 创建示例数据
np.random.seed(42)
# 生成时间序列数据
date_rng = pd.date_range(start='2023-01-01', end='2023-12-31', freq='D')
data = {
'date': [],
'product': [],
'sales': [],
'region': []
}
for product in ['A', 'B', 'C']:
for region in ['North', 'South', 'East', 'West']:
dates = pd.date_range(start='2023-01-01', periods=365, freq='D')
data['date'].extend(dates)
data['product'].extend([product] * 365)
data['region'].extend([region] * 365)
data['sales'].extend(np.random.randint(10, 100, 365))
df = pd.DataFrame(data)
print("数据形状:", df.shape)
print("\n数据预览:")
print(df.head())
基础分组操作
# 设置日期为索引
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
# 按产品和地区分组并计算统计量
group_stats = df.groupby(['product', 'region']).agg({
'sales': ['sum', 'mean', 'std', 'min', 'max']
}).round(2)
print("分组统计:")
print(group_stats.head())
时序分组统计
按年/月/周分组
# 按年月分组
monthly_stats = df.groupby(['product', 'region',
df.index.year,
df.index.month])['sales'].agg(['sum', 'mean', 'count'])
monthly_stats.columns = ['total_sales', 'avg_sales', 'days_count']
print("\n月度统计:")
print(monthly_stats.head(10))
# 按周分组
weekly_stats = df.groupby(['product', df.index.isocalendar().week])['sales'].sum()
print("\n周度销量:")
print(weekly_stats.head())
滚动窗口计算
# 7天滚动平均
df['rolling_7d_mean'] = df.groupby(['product', 'region'])['sales']\
.transform(lambda x: x.rolling(window=7, min_periods=1).mean())
# 30天滚动总和
df['rolling_30d_sum'] = df.groupby(['product', 'region'])['sales']\
.transform(lambda x: x.rolling(window=30, min_periods=1).sum())
print("\n滚动计算示例:")
print(df[df['product'] == 'A'].head(10))
高级时序分析
同比和环比计算
# 准备数据
df_reset = df.reset_index()
df_reset['year'] = df_reset['date'].dt.year
df_reset['month'] = df_reset['date'].dt.month
# 环比计算
monthly_sales = df_reset.groupby(['product', 'region', 'year', 'month'])['sales'].sum().reset_index()
monthly_sales.sort_values(['product', 'region', 'year', 'month'], inplace=True)
# 计算环比增长率
monthly_sales['mom_change'] = monthly_sales.groupby(['product', 'region'])['sales']\
.pct_change() * 100
# 计算同比增长率
monthly_sales['yoy_change'] = monthly_sales.groupby(['product', 'region'])['sales']\
.transform(lambda x: x.pct_change(periods=12)) * 100
print("\n同比环比分析:")
print(monthly_sales[monthly_sales['product'] == 'A'].head(15))
季节性分析
# 添加季节标签
def get_season(month):
if month in [3, 4, 5]:
return 'Spring'
elif month in [6, 7, 8]:
return 'Summer'
elif month in [9, 10, 11]:
return 'Autumn'
else:
return 'Winter'
df_reset['season'] = df_reset['month'].apply(get_season)
# 季节性分组统计
seasonal_stats = df_reset.groupby(['product', 'region', 'season'])['sales'].agg([
'sum', 'mean', 'std'
]).round(2)
print("\n季节性分析:")
print(seasonal_stats)
复杂时序分组案例
案例1:销售波动分析
# 计算每日波动率
df['daily_change'] = df.groupby(['product', 'region'])['sales'].pct_change()
# 找出异常波动
threshold = 0.5 # 50%波动阈值
df['is_anomaly'] = abs(df['daily_change']) > threshold
# 统计各产品异常天数
anomaly_stats = df[df['is_anomaly']].groupby(['product', 'region']).size()
print("\n异常波动统计:")
print(anomaly_stats)
案例2:累计达成率分析
# 假设月度目标是每个产品地区组合1000
monthly_target = 1000
# 计算累计销量和达成率
df['monthly_cumsum'] = df.groupby(['product', 'region', df.index.month])['sales'].cumsum()
df['achievement_rate'] = (df['monthly_cumsum'] / monthly_target * 100).round(1)
# 查看每月末的达成情况
monthly_end = df.groupby(['product', 'region', df.index.month]).last()
print("\n月度目标达成率:")
print(monthly_end[['achievement_rate']].head(10))
案例3:趋势分析
# 线性回归分析趋势
from scipy import stats
def trend_analysis(group):
x = np.arange(len(group))
y = group['sales'].values
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
return pd.Series({
'slope': slope,
'r_squared': r_value**2,
'p_value': p_value,
'trend': '上升' if slope > 0 else '下降'
})
# 各产品地区的销售趋势
trend_results = df.groupby(['product', 'region']).apply(trend_analysis)
print("\n销售趋势分析:")
print(trend_results)
数据可视化
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 时间序列可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 1. 各产品月度销量趋势
monthly_product = df_reset.groupby(['product', 'year', 'month'])['sales'].sum().reset_index()
monthly_product['date'] = pd.to_datetime(monthly_product[['year', 'month']].assign(day=1))
for product in ['A', 'B', 'C']:
product_data = monthly_product[monthly_product['product'] == product]
axes[0, 0].plot(product_data['date'], product_data['sales'],
label=f'产品{product}', marker='o')
axes[0, 0].set_title('各产品月度销量趋势')
axes[0, 0].legend()
axes[0, 0].set_xlabel('日期')
axes[0, 0].set_ylabel('销量')
# 2. 地区销量热力图
region_monthly = df_reset.pivot_table(
values='sales',
index=df_reset['date'].dt.month,
columns='region',
aggfunc='sum'
)
sns.heatmap(region_monthly, ax=axes[0, 1], cmap='YlOrRd', annot=True, fmt='.0f')
axes[0, 1].set_title('各地区月度销量分布')
# 3. 滚动平均对比
product_a = df[df['product'] == 'A'].groupby('region')['rolling_7d_mean']
for region in product_a.groups.keys():
axes[1, 0].plot(product_a.get_group(region).head(100),
label=f'{region}', alpha=0.7)
axes[1, 0].set_title('产品A 7天滚动平均')
axes[1, 0].legend()
# 4. 异常分布
anomaly_counts = df[df['is_anomaly']].groupby(['product', 'region']).size().unstack()
anomaly_counts.plot(kind='bar', ax=axes[1, 1])
axes[1, 1].set_title('异常波动分布')
axes[1, 1].set_ylabel('异常次数')
plt.tight_layout()
plt.show()
完整分析Pipeline
def complete_time_series_analysis(df):
"""
完整的时序分组分析流程
"""
# 1. 数据预处理
df = df.copy()
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
# 2. 基础统计
basic_stats = df.groupby(['product', 'region']).agg({
'sales': ['mean', 'std', 'min', 'max', 'count']
})
# 3. 时序特征
df['month'] = df.index.month
df['quarter'] = df.index.quarter
df['weekday'] = df.index.weekday
# 4. 滚动统计
rolling_stats = df.groupby(['product', 'region'])['sales'].rolling(7).agg([
'mean', 'std', 'min', 'max'
]).round(2)
# 5. 增长率分析
growth_rates = df.groupby(['product', 'region', 'month'])['sales'].sum()\
.groupby(level=[0, 1]).pct_change() * 100
return {
'basic_stats': basic_stats,
'rolling_stats': rolling_stats,
'growth_rates': growth_rates,
'processed_data': df
}
# 运行完整分析
results = complete_time_series_analysis(df)
print("基础统计:")
print(results['basic_stats'])
print("\n增长率分析:")
print(results['growth_rates'].head())
这些案例覆盖了Pandas分组时序分析的主要应用场景,你可以根据实际需求进行调整和使用。