You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在带股票-日期多层索引的Pandas中计算历史前置均值

问题:按股票分组计算前置日期的P/Sales均值?

问题背景

我有一个多层索引的DataFrame,第一层为股票代码(Ticker),第二层为日期,示例代码如下:

import pandas as pd
import numpy as np

arrays = [
    np.array(["MSFT", "MSFT", "MSFT", "MSFT", "GOOG", "GOOG", "GOOG", "GOOG"]),
    np.array([pd.to_datetime("2022-04-05"), pd.to_datetime("2022-04-06"), pd.to_datetime("2022-04-07"), pd.to_datetime("2022-04-08"),pd.to_datetime("2022-04-05"), pd.to_datetime("2022-04-06"), pd.to_datetime("2022-04-07"), pd.to_datetime("2022-04-08")]),
]

df = pd.DataFrame(np.random.randn(8, 1), index=arrays, columns={"P/Sales"})
df

生成的DataFrame如下:

股票代码日期P/Sales
MSFT2022-04-05 00:00:00-1.1648041378350011
MSFT2022-04-06 00:00:00-2.352493882690841
MSFT2022-04-07 00:00:000.6047960443400636
MSFT2022-04-08 00:00:001.533852852883288
GOOG2022-04-05 00:00:002.0738583230363195
GOOG2022-04-06 00:00:00-1.887463559617715
GOOG2022-04-07 00:00:000.49868465858420324
GOOG2022-04-08 00:00:000.900527823711884

需求说明

我希望新增一列,存储对应股票当前日期之前所有日期的P/Sales列均值。目前通过嵌套循环实现该需求,但嵌套循环效率较低,想使用更高效的方法(比如expanding.mean()),但无法正确编写按股票分组且仅计算前置日期均值的语法。

当前实现代码

for ticker in  df.reset_index()['Ticker'].unique():    
    for date in df.loc[ticker].index:
      filtered_df = df.loc[ticker].loc[(df.loc[ticker].index < date)]
      mean = np.mean(np.asarray(filtered_df['P/Sales']))
      df.loc[(ticker,date),"Mean"] = mean

df

运行后得到的结果如下:

股票代码日期P/Sales均值
MSFT2022-04-05 00:00:00-1.4361186774548342NaN
MSFT2022-04-06 00:00:000.5922672022039192-1.4361186774548342
MSFT2022-04-07 00:00:000.4844687977324626-0.42192573762545754
MSFT2022-04-08 00:00:00-0.4125514467122677-0.11979422583948417
GOOG2022-04-05 00:00:00-0.30860020353979284NaN
GOOG2022-04-06 00:00:000.1189685515177034-0.30860020353979284
GOOG2022-04-07 00:00:001.1730395696068878-0.09481582601104471
GOOG2022-04-08 00:00:00-0.97783230045222750.3278026391949328

高效解决方案

可以通过按股票代码分组,结合expanding().mean()和shift()实现需求,完全替代嵌套循环,效率大幅提升:

# 按多层索引第一层(股票代码)分组,计算前置日期均值
df['Mean'] = df.groupby(level=0)['P/Sales'].expanding().mean().shift().reset_index(level=0, drop=True)

代码解析

  • groupby(level=0):针对多层索引的第一层(股票代码)分组,确保每个股票的计算独立进行
  • expanding().mean():对每个分组计算从第一行到当前行的累积均值
  • shift():将累积均值结果下移一行,这样当前行的均值就对应之前所有日期的均值,第一行自然变为NaN(符合无前置数据的逻辑)
  • reset_index(level=0, drop=True):移除分组后新增的层级索引,保证结果能和原DataFrame的索引完美匹配

该方法运行结果和嵌套循环完全一致,但时间复杂度更低,尤其适合处理大规模数据集。

内容的提问来源于stack exchange,提问作者David Bell

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 03:35:19