本文目录导读:

我来详细讲解如何使用 Pandas 进行数据分组重采样(resampling)和伸缩(scaling)操作。
基础准备
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# 创建示例数据
np.random.seed(42)
# 生成时间序列数据
dates = pd.date_range('2024-01-01', periods=100, freq='D')
df = pd.DataFrame({
'date': dates,
'sales': np.random.randint(100, 500, 100),
'category': np.random.choice(['A', 'B', 'C'], 100),
'price': np.random.uniform(10, 50, 100).round(2)
})
print("原始数据预览:")
print(df.head())
print(f"\n数据形状: {df.shape}")
时间序列重采样
1 基本重采样
# 设置日期为索引
df_time = df.set_index('date')
# 按周重采样
weekly_data = df_time['sales'].resample('W').sum()
print("按周汇总:")
print(weekly_data.head())
# 按月重采样
monthly_data = df_time['sales'].resample('M').mean()
print("\n按月平均值:")
print(monthly_data.head())
# 按季度重采样
quarterly_data = df_time['sales'].resample('Q').agg(['sum', 'mean', 'std'])
print("\n按季度统计:")
print(quarterly_data.head())
2 不同的聚合函数
# 多种聚合方式
resampled_df = df_time.resample('W').agg({
'sales': ['sum', 'mean', 'max', 'min'],
'price': ['mean', 'std']
})
print("多列多函数重采样:")
print(resampled_df.head())
分组重采样
1 按类别分组后重采样
# 按类别和时间分组重采样
df_grouped = df.set_index('date')
# 按类别分组后按月重采样
category_monthly = df_grouped.groupby('category').resample('M')['sales'].agg(['sum', 'mean'])
print("按类别和月份分组:")
print(category_monthly.head(10))
# 更复杂的聚合
pivoted_data = df_grouped.groupby('category').resample('W').agg({
'sales': 'sum',
'price': 'mean'
}).round(2)
print("\n按类别和周的统计:")
print(pivoted_data.head(10))
2 多级分组重采样
# 添加更多分组维度
df['region'] = np.random.choice(['North', 'South', 'East', 'West'], 100)
# 多级分组重采样
multi_grouped = df.set_index('date').groupby(['category', 'region']).resample('M')['sales'].sum()
print("多级分组重采样:")
print(multi_grouped.head(10))
数据伸缩(Scaling)
1 归一化(Min-Max Scaling)
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# Min-Max 归一化
def min_max_scaling(group):
scaler = MinMaxScaler()
group['sales_scaled'] = scaler.fit_transform(group[['sales']])
return group
# 按类别分组后归一化
df_scaled = df.groupby('category').apply(min_max_scaling)
print("Min-Max 归一化结果:")
print(df_scaled[df_scaled['category'] == 'A'].head())
2 标准化(Z-score Scaling)
# 标准化
def standard_scaling(group):
scaler = StandardScaler()
group['sales_standardized'] = scaler.fit_transform(group[['sales']])
group['price_standardized'] = scaler.fit_transform(group[['price']])
return group
# 按类别分组后标准化
df_standardized = df.groupby('category').apply(standard_scaling)
print("\n标准化结果:")
print(df_standardized[df_standardized['category'] == 'B'].head())
实用案例
案例1:销售数据分析
# 创建销售数据
sales_data = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=365, freq='D'),
'product': np.random.choice(['Product_A', 'Product_B', 'Product_C'], 365),
'sales_amount': np.random.uniform(1000, 5000, 365).round(2),
'units_sold': np.random.randint(10, 100, 365)
})
# 按月分析每个产品的销售趋势
monthly_trend = (sales_data.set_index('date')
.groupby('product')
.resample('M')
.agg({
'sales_amount': 'sum',
'units_sold': 'sum'
}))
print("月度销售趋势:")
print(monthly_trend.head(10))
# 计算每个产品的月度增长率
for product in monthly_trend.index.get_level_values(0).unique():
product_data = monthly_trend.loc[product]
product_data['growth_rate'] = product_data['sales_amount'].pct_change() * 100
print(f"\n{product} 月度增长率:")
print(product_data[['sales_amount', 'growth_rate']].head())
案例2:股票数据分析
# 模拟股票数据
stock_data = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=100, freq='D'),
'stock': np.random.choice(['AAPL', 'GOOGL', 'MSFT'], 100),
'price': np.random.uniform(150, 200, 100).round(2),
'volume': np.random.randint(1000000, 5000000, 100)
})
# 按周分析股票
weekly_stock = (stock_data.set_index('date')
.groupby('stock')
.resample('W')
.agg({
'price': ['first', 'last', 'min', 'max', 'mean'],
'volume': 'sum'
}))
print("周度股票分析:")
print(weekly_stock.head(10))
# 计算每周收益率
def calculate_weekly_return(group):
weekly_return = (group['price'].resample('W').last() /
group['price'].resample('W').first() - 1) * 100
return weekly_return
stock_returns = stock_data.set_index('date').groupby('stock').apply(calculate_weekly_return)
print("\n每周收益率:")
print(stock_returns.head())
高级技巧
1 自定义聚合函数
def custom_agg(group):
"""自定义聚合函数"""
return pd.Series({
'mean': group.mean(),
'median': group.median(),
'iqr': group.quantile(0.75) - group.quantile(0.25),
'cv': group.std() / group.mean() * 100 # 变异系数
})
# 应用自定义函数
custom_results = (df.set_index('date')
.groupby('category')
.resample('M')
.apply(custom_agg))
print("自定义聚合结果:")
print(custom_results.head())
2 滚动窗口分析
# 滚动窗口计算
rolling_stats = (df.set_index('date')
.groupby('category')['sales']
.rolling(window=7)
.agg(['mean', 'std', 'min', 'max']))
print("7天滚动统计:")
print(rolling_stats.head(10))
# 绘制滚动平均
category_a = df[df['category'] == 'A'].set_index('date')['sales']
category_a_rolling = category_a.rolling(window=7).mean()
plt.figure(figsize=(12, 6))
plt.plot(category_a.index, category_a.values, label='原始数据', alpha=0.5)
plt.plot(category_a_rolling.index, category_a_rolling.values, label='7天滚动平均')'类别A的销售额趋势')
plt.xlabel('日期')
plt.ylabel('销售额')
plt.legend()
plt.show()
数据导出与保存
# 保存处理后的数据
def save_processed_data(df, filename):
"""保存处理后的数据"""
df.to_csv(filename, index=True)
print(f"数据已保存到 {filename}")
# 保存不同维度的分析结果
save_processed_data(weekly_data, 'weekly_sales.csv')
save_processed_data(monthly_trend, 'monthly_trend.csv')
save_processed_data(weekly_stock, 'weekly_stock_analysis.csv')
# 也可以保存为Excel格式(多表)
with pd.ExcelWriter('analysis_report.xlsx') as writer:
weekly_data.to_excel(writer, sheet_name='周度销售')
monthly_trend.to_excel(writer, sheet_name='月度趋势')
weekly_stock.to_excel(writer, sheet_name='股票分析')
总结要点
- 重采样频率:'D'(天)、'W'(周)、'M'(月)、'Q'(季度)、'Y'(年)
- 聚合函数:sum、mean、std、min、max、first、last
- 分组维度:按类别、地区等多维度组合
- 数据伸缩:归一化、标准化等预处理方法
- 窗口函数:滚动计算、移动平均等时间序列分析
这些技巧可以帮助你更有效地处理时间序列数据,进行深入的数据分析和洞察。