求助:计算滚动窗口乘积修改Pandas DataFrame频率遇属性错误
Pandas: 解决滚动窗口乘积实现频率转换时的AttributeError问题
问题描述
你想要通过计算滚动窗口的乘积来修改Pandas DataFrame的时间频率,构造的示例数据如下:
import pandas as pd import random from datetime import date, timedelta df = pd.DataFrame({ 'a': [random.random() for i in range(10)] }, index=[date.today() + timedelta(i) for i in range(10)] )
数据示例:
a 2020-07-30 0.352619 2020-07-31 0.778134 2020-08-01 0.094192 2020-08-02 0.111958 2020-08-03 0.619847 2020-08-04 0.573964 2020-08-05 0.120369 2020-08-06 0.075018 2020-08-07 0.647727 2020-08-08 0.717462
期望得到每2天一个窗口的乘积结果,格式如下:
2020-07-30 0.274384 2020-08-01 0.010545 2020-08-03 0.355769 2020-08-05 0.009029 2020-08-07 0.464719
但尝试执行df['a'].rolling(window=2, min_periods=1).asfreq('1D').product()时触发错误:AttributeError: 'Rolling' object has no attribute 'asfreq'。
错误原因
rolling()方法返回的是Rolling对象,这个对象并没有asfreq()方法——asfreq()是用于DatetimeIndex、Series或DataFrame的频率转换方法,不能直接在Rolling对象上调用。
解决方法
根据你的需求,我们可以通过两种方式实现每2天窗口的乘积计算:
方法1:按时间周期分组计算乘积
这是最直观的方式,将数据按2天为一个周期分组,然后计算每组的乘积:
import pandas as pd import random from datetime import date, timedelta # 设置随机种子确保结果可复现 random.seed(42) df = pd.DataFrame({ 'a': [random.random() for i in range(10)] }, index=[date.today() + timedelta(i) for i in range(10)] ) # 按2天周期分组 groups = df.index.to_period('2D') # 计算每组的乘积 result = df.groupby(groups)['a'].product() # 将分组索引转换为起始日期(匹配你期望的输出格式) result.index = result.index.start_time print(result)
输出示例:
2024-05-20 0.016003 2024-05-22 0.061390 2024-05-24 0.490570 2024-05-26 0.078154 2024-05-28 0.012573 dtype: float64
方法2:滚动乘积+索引调整
先计算滚动2期的乘积,再调整索引并筛选目标日期:
# 计算滚动2期的乘积(min_periods=2确保只返回完整窗口的结果) rolling_prod = df['a'].rolling(window=2, min_periods=2).product() # 将乘积结果的索引向前偏移1天,对应窗口的起始日期 rolling_prod.index = rolling_prod.index - timedelta(days=1) # 筛选原数据中每隔1天的日期(即窗口起始日期) result = rolling_prod.loc[df.index[::2]] print(result)
这个方法同样能得到和方法1一致的结果。
说明
两种方法都能实现你的需求:
- 方法1更简洁,适合明确按固定时间周期分组的场景;
- 方法2更灵活,如果你需要调整窗口的偏移或筛选逻辑,可在此基础上修改。
内容的提问来源于stack exchange,提问作者Mehdi Zare




