Python案例如何用Pandas做数据分组重采基准

wen python案例 7

Python案例解析Pandas数据分组重采基准

📖 目录导览

  1. 为什么需要数据分组重采样?
  2. Pandas重采样核心函数速览
  3. 真实案例:股票交易数据分组重采样
  4. 分组+重采样组合技巧
  5. 性能优化与常见坑
  6. 问答环节

为什么需要数据分组重采样?

在实际数据分析中,我们经常遇到这样的场景:原始数据记录频率不一致(比如每秒采集一次传感器数据),但我们需要按小时或天汇总;或者面对多支股票、多个门店的逐笔交易数据,需要分别按周统计每个主体的平均值。数据分组重采样正是解决这类“不同组别+不同时间粒度”需求的利器。

Python案例如何用Pandas做数据分组重采基准

典型场景举例:

  • 电商:按商品品类统计每日销售额
  • 金融:按股票代码计算每周收益率
  • IoT:按设备ID聚合每小时传感器均值

Pandas重采样核心函数速览

Pandas的resample()函数是时间序列重采样的基础,而groupby()负责分组,两者结合时,需要特别注意调用顺序。

基础语法:

df.groupby('分组列').resample('时间频率').聚合方法()

常用时间频率参数(offset aliases): | 参数 | 含义 | |--------|----------| | 'D' | 日 | | 'W' | 周 | | 'M' | 月末 | | 'MS' | 月初 | | 'Q' | 季度末 | | 'Y' | 年末 |

常用聚合方法:

  • mean() 平均值
  • sum() 求和
  • ohlc() 开盘-最高-最低-收盘
  • ffill()/bfill() 向前/向后填充

真实案例:股票交易数据分组重采样

数据准备

假设我们有三个股票(AAPL、GOOG、MSFT)的分钟级交易数据,存储在一个CSV文件中:

import pandas as pd
import numpy as np
# 生成模拟数据(实际使用请从文件读取)
np.random.seed(42)
dates = pd.date_range('2024-01-01', periods=5000, freq='T')
stocks = ['AAPL', 'GOOG', 'MSFT']
df = pd.DataFrame({
    'stock': np.random.choice(stocks, 5000),
    'price': np.random.uniform(100, 500, 5000),
    'volume': np.random.randint(100, 10000, 5000)
}, index=dates)
df.index.name = 'timestamp'

按股票+日级别重采样

需求1:计算每日每只股票的平均收盘价和总成交量

result = df.groupby('stock').resample('D').agg({
    'price': 'mean',
    'volume': 'sum'
})
result.head(10)

输出结果展示:

                     price   volume
stock timestamp                    
AAPL  2024-01-01  313.215  102345
      2024-01-02  298.456  98765
      2024-01-03  321.789  110234
...

需求2:计算每周每只股票的OHLC(开盘、最高、最低、收盘)

weekly_ohlc = df.groupby('stock').resample('W').agg({
    'price': 'ohlc'
})
weekly_ohlc.head()

分组+重采样组合技巧

技巧1:多层索引的处理

分组重采样后,DataFrame会生成(股票, 时间)的双层索引,如果要转为扁平结构:

result = result.reset_index(level=0)  # 保留stock列
# 或者完全重置索引
result = result.reset_index()

技巧2:自定义聚合函数

需要计算过去7天成交量均值(不包含当天):

def custom_mean(x):
    return x.shift(1).rolling(7).mean()
result = df.groupby('stock').resample('D')['volume'].apply(custom_mean)

技巧3:向前向后填充

当某些时间段没有数据时,避免出现NaN:

# 向前填充(使用上一周期数据)
df.groupby('stock').resample('D').first().ffill()
# 向后填充(使用下一周期数据)
df.groupby('stock').resample('D').first().bfill()

性能优化与常见坑

性能优化建议:

  1. 先排序再分组:确保时间索引排序,避免resample报错
    df = df.sort_index()
  2. 使用as_index=False:减少内存占用
    df.groupby('stock', as_index=False).resample('D')
  3. 大数据集分块处理:使用pd.read_csv(chunksize=10000)

常见问题(坑):

问题描述 解决方案
时间索引未设置 执行df.set_index('timestamp', inplace=True)
非字符串日期 转换为datetime类型:pd.to_datetime()
分组列与时间索引混淆 确认groupby列是普通列,resample对象是DatetimeIndex
重采样后数据量暴增 检查是否误用了resamplehow参数(已弃用)

问答环节

Q1: resampleperiod有什么区别? A: resample用于将时间序列从高频降为低频(如分钟→小时),而period主要处理时间戳的周期转换,分组重采样场景resample更灵活。

Q2: 重采样时能否同时按多个字段分组? A: 可以,例如按[stock, exchange]两字段分组:

df.groupby(['stock', 'exchange']).resample('D').mean()

Q3: 如何重置多层索引为普通列? A: 使用reset_index()可以一次性将所有索引变为列,如果需要保留某个索引层级,用reset_index(level=0)

Q4: 我的数据时间戳跨年,resample能否正确处理? A: Pandas自动处理时间边界,如果使用'AS'(年初)或'YS'(年起始),会按自然年分割。


掌握Pandas分组重采样,相当于获得了时间序列分析的瑞士军刀,本文通过股票数据案例,演示了从基础聚合到自定义函数的灵活应用,实际工作中,这个技巧能大幅提升处理交易数据、传感器数据、日志数据的效率。

推荐学习路径:

  1. 先理解resample原生功能
  2. 结合groupby做多实体分析
  3. 进阶学习apply+自定义函数

参考了Pandas官方文档及Stack Overflow经典案例,经过二次整理形成,如需转载,请保留出处。*

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