本文目录导读:

我来为你详细讲解如何使用Pandas进行数据分组重采样,重采样通常用于时间序列数据,包括降采样(高频→低频)和升采样(低频→高频)。
基本设置和示例数据
import pandas as pd
import numpy as np
from datetime import datetime
# 创建示例时间序列数据
dates = pd.date_range('2023-01-01', periods=100, freq='H')
data = pd.DataFrame({
'date': dates,
'value': np.random.randn(100),
'category': np.random.choice(['A', 'B', 'C'], 100)
})
print(data.head())
设置时间索引
重采样需要时间戳索引:
# 将日期列设置为索引
data.set_index('date', inplace=True)
print(data.index)
基本降采样(高频→低频)
1 按小时重采样为按天
# 每日均值
daily_mean = data['value'].resample('D').mean()
print(daily_mean.head())
# 每日求和
daily_sum = data['value'].resample('D').sum()
print(daily_sum.head())
2 多种聚合操作
# 同时进行多种聚合
daily_stats = data['value'].resample('D').agg(['mean', 'std', 'min', 'max', 'count'])
print(daily_stats.head())
分组重采样(核心功能)
1 按类别分组后重采样
# 方法1:先分组,再重采样
grouped_resampled = data.groupby('category').resample('D')['value'].mean()
print(grouped_resampled.head(10))
# 方法2:使用reset_index()使结果更清晰
grouped_resampled_clean = data.groupby('category').resample('D')['value'].mean().reset_index()
print(grouped_resampled_clean.head(10))
2 多列分组重采样
# 多列分组并重采样
multi_group = data.groupby(['category', data.index.month]).resample('W')['value'].agg(['mean', 'count'])
print(multi_group.head(10))
实际应用案例
1 销售数据分析
# 创建销售数据
sales_data = pd.DataFrame({
'date': pd.date_range('2023-01-01', periods=1000, freq='H'),
'store': np.random.choice(['Store_A', 'Store_B', 'Store_C'], 1000),
'product': np.random.choice(['Product_1', 'Product_2', 'Product_3'], 1000),
'sales': np.random.randint(1, 100, 1000),
'revenue': np.random.uniform(10, 1000, 1000)
})
sales_data.set_index('date', inplace=True)
# 按店铺和产品分组,按天重采样求和
daily_sales = sales_data.groupby(['store', 'product']).resample('D')['sales', 'revenue'].sum()
print(daily_sales.head(10))
2 股票数据分析
# 创建股票数据
stock_data = pd.DataFrame({
'date': pd.date_range('2023-01-01', periods=5000, freq='5min'),
'stock': np.random.choice(['AAPL', 'GOOGL', 'MSFT'], 5000),
'price': np.random.uniform(100, 200, 5000),
'volume': np.random.randint(1000, 10000, 5000)
})
stock_data.set_index('date', inplace=True)
# 按股票分组,按天重采样计算OHLC
def ohlc_resample(group):
return group.resample('D').agg({
'price': ['first', 'max', 'min', 'last'],
'volume': 'sum'
})
daily_ohlc = stock_data.groupby('stock').apply(ohlc_resample)
print(daily_ohlc.head(10))
高级重采样技巧
1 自定义重采样函数
def custom_resample(x):
"""自定义重采样函数"""
return {
'mean': x.mean(),
'median': x.median(),
'range': x.max() - x.min(),
'volatility': x.std() / x.mean() if x.mean() != 0 else 0
}
# 应用自定义函数
custom_stats = data.groupby('category').resample('W').apply(
lambda x: pd.Series(custom_resample(x['value']))
)
print(custom_stats.head(10))
2 填充缺失值(升采样)
# 创建有缺失的时间序列
dates_with_gaps = pd.date_range('2023-01-01', periods=10, freq='D')
gap_data = pd.DataFrame({
'date': dates_with_gaps,
'value': [1, 2, np.nan, 4, np.nan, 6, 7, np.nan, 9, 10],
'category': ['A', 'B'] * 5
})
gap_data.set_index('date', inplace=True)
# 升采样并填充
upsampled = gap_data.groupby('category').resample('12H').asfreq()
upsampled_filled = upsampled.groupby('category').fillna(method='ffill')
print(upsampled_filled.head(10))
3 不同频率的重采样
# 多种重采样频率
frequencies = {
'hourly': 'H',
'daily': 'D',
'weekly': 'W',
'monthly': 'M',
'quarterly': 'Q'
}
for name, freq in frequencies.items():
result = data.groupby('category').resample(freq)['value'].mean()
print(f"{name} stats:\n", result.head())
print("-" * 40)
性能优化技巧
# 大数据集性能优化
def optimized_groupby_resample(df, group_col, time_col, value_col, freq):
"""优化的分组重采样函数"""
# 设置时间索引
df = df.set_index(time_col)
# 使用transform避免重复计算
grouped = df.groupby(group_col)
# 并行处理(大文件使用)
results = []
for name, group in grouped:
resampled = group[value_col].resample(freq).mean()
resampled.name = name
results.append(resampled)
return pd.concat(results, keys=[g for g in df[group_col].unique()])
# 使用示例
result = optimized_groupby_resample(
data,
group_col='category',
time_col='date',
value_col='value',
freq='D'
)
print(result.head())
完整示例:数据分析工作流
# 完整的分析工作流
def complete_analysis(df, time_col, group_cols, value_cols, resample_freq):
"""
完整的分组重采样分析
参数:
- df: DataFrame
- time_col: 时间列名
- group_cols: 分组列名列表
- value_cols: 值列名列表
- resample_freq: 重采样频率
"""
# 1. 数据准备
df = df.copy()
df[time_col] = pd.to_datetime(df[time_col])
df.set_index(time_col, inplace=True)
# 2. 按组重采样
results = {}
for group_col in group_cols:
resampled_data = df.groupby(group_col).resample(resample_freq)[value_cols].agg([
'mean', 'std', 'sum', 'count'
])
results[group_col] = resampled_data
# 3. 统计分析
stats = {}
for group_col, data in results.items():
stats[group_col] = {
'total_observations': data['count'].sum().sum(),
'mean_values': data['mean'].mean(),
'std_values': data['std'].mean()
}
return results, stats
# 应用分析
results, stats = complete_analysis(
data,
time_col='date',
group_cols=['category'],
value_cols=['value'],
resample_freq='W'
)
# 显示结果
for group, stat in stats.items():
print(f"\nGroup: {group}")
for key, value in stat.items():
print(f"{key}: {value:.2f}")
print("\n重采样数据样例:")
print(results['category'].head())
常见重采样频率代码
# 常用频率代码
freq_codes = {
'秒': 'S',
'分钟': 'T', # 或 'min'
'小时': 'H',
'天': 'D',
'周': 'W',
'月': 'M',
'季度': 'Q',
'年': 'Y',
'工作日': 'B',
'月初': 'MS',
'季度初': 'QS'
}
# 偏移量示例
offset_examples = {
'每2小时': '2H',
'每3天': '3D',
'每两周': '2W',
'每半年': '6M'
}
这些示例涵盖了大多数常见的分组重采样场景,根据你的具体需求选择合适的重采样频率和聚合函数即可。