Python案例如何用Pandas做数据分组重采替代

wen python案例 5

我来通过一个实际案例演示如何使用Pandas进行数据分组重采样(GroupBy + Resample)。

Python案例如何用Pandas做数据分组重采替代

案例:股票交易数据分析

假设我们有多只股票的分钟级交易数据,需要按天汇总每只股票的统计指标。

创建示例数据

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
# 创建示例数据
np.random.seed(42)
# 生成日期范围
date_range = pd.date_range('2024-01-01', '2024-01-07', freq='5min')
# 创建多只股票的数据
stocks = ['AAPL', 'GOOGL', 'MSFT']
data_list = []
for stock in stocks:
    n = len(date_range)
    stock_data = pd.DataFrame({
        'stock': stock,
        'timestamp': date_range,
        'price': 100 + np.random.randn(n).cumsum() * 0.5,
        'volume': np.random.randint(1000, 10000, n)
    })
    data_list.append(stock_data)
# 合并所有数据
df = pd.concat(data_list, ignore_index=True)
print("原始数据预览:")
print(df.head(10))
print(f"\n数据形状: {df.shape}")

设置时间索引并分组重采样

# 设置时间索引
df.set_index('timestamp', inplace=True)
# 按股票分组,并按天重采样
daily_stats = df.groupby('stock').resample('1D').agg({
    'price': ['first', 'last', 'max', 'min', 'mean', 'std'],
    'volume': ['sum', 'mean', 'max']
})
print("每日股票统计:")
print(daily_stats.head(20))

重命名列名

# 重命名多级列名
daily_stats.columns = ['_'.join(col).strip() for col in daily_stats.columns.values]
daily_stats = daily_stats.reset_index()
print("重命名后的数据:")
print(daily_stats.head(10))

高级重采样操作

# 计算每只股票的日收益率
price_daily = df.groupby('stock')['price'].resample('1D').last()
returns = price_daily.groupby('stock').pct_change() * 100
print("每日收益率 (%):")
print(returns)
# 计算滚动统计量
rolling_stats = df.groupby('stock').rolling(window='2D').agg({
    'price': ['mean', 'std'],
    'volume': ['sum']
})
print("\n滚动统计(2天窗口):")
print(rolling_stats.head(20))

复杂数据处理案例

# 计算每周开盘价、最高价、最低价、收盘价和成交量总和
weekly_data = df.groupby('stock').resample('1W').agg({
    'price': ['first', 'max', 'min', 'last'],
    'volume': 'sum'
})
weekly_data.columns = ['open', 'high', 'low', 'close', 'volume']
weekly_data = weekly_data.reset_index()
print("周度数据(OHLC格式):")
print(weekly_data)
# 计算每只股票午前和午后的平均成交量
def time_of_day(hour):
    if hour < 12:
        return 'morning'
    else:
        return 'afternoon'
df['time_period'] = df.index.hour.map(time_of_day)
period_volume = df.groupby(['stock', 'time_period'])['volume'].mean()
print("\n午前午后平均成交量:")
print(period_volume)

实际应用:异常检测

# 检测价格异常波动
def detect_outliers(group):
    mean = group['price'].mean()
    std = group['price'].std()
    return (group['price'] - mean).abs() > 2 * std
outliers = df.groupby('stock').apply(detect_outliers)
outlier_points = df[outliers]
print(f"发现异常点数量: {len(outlier_points)}")
if len(outlier_points) > 0:
    print("\n异常点示例:")
    print(outlier_points.head())

常见重采样频率

# 不同时间频率
freqs = {
    'B': '工作日',
    'W': '周',
    'M': '月',
    'Q': '季度',
    'Y': '年',
    'H': '小时',
    'T': '分钟',
    'S': '秒'
}

处理缺失数据

# 重采样后填充缺失值
daily_data = df.groupby('stock').resample('1D').agg({
    'price': 'mean'
})
# 前向填充
daily_data_filled = daily_data.fillna(method='ffill')
# 线性插值
daily_data_interpolated = daily_data.interpolate()

自定义聚合函数

# 自定义聚合函数
def price_range(prices):
    return prices.max() - prices.min()
custom_agg = df.groupby('stock').resample('1D').agg({
    'price': ['mean', price_range],
    'volume': 'sum'
})

这个案例展示了Pandas数据分组重采样的核心用法,包括:

  • 基本分组重采样
  • 多级列名处理
  • 滚动窗口计算
  • 时间周期聚合
  • 自定义函数应用

你可以根据实际业务需求调整重采样频率、聚合函数和处理逻辑。

抱歉,评论功能暂时关闭!