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

如何实现按递增窗口计算pct_change?适配类似rolling的min_periods功能

问题:自定义pct_change的计算周期(从1逐步递增到指定值)

假设我有如下序列:

import pandas as pd
s = pd.Series([90, 91, 85, 95])

当用periods=2计算百分比变化(pct_change)时,得到的结果是:

s.pct_change(periods=2)

输出:

0         NaN
1         NaN
2   -0.055556
3    0.043956
dtype: float64

但如果是多年数据,想用pct_change(365)计算年同比滚动回报,前365个值都会变成NaN,相当于丢失了一年的数据。我希望做个折中:从period=1开始,逐步递增到指定的periods值进行计算,最终得到类似下面的结果(两种形式均可):

第一种结果:

0         NaN
1    0.011111
2   -0.055556
3    0.043956
dtype: float64

第二种结果:

0           0
1    0.011111
2   -0.055556
3    0.043956
dtype: float64

我知道rolling方法有min_periods参数可以实现类似的灵活计算,但pct_change没有对应的参数,请问这种需求是否可行?


解决方案

可行,我们可以通过动态调整每个位置的对比期数来实现,核心思路是:对索引为i的元素,当i < 指定periods时,用period=i计算百分比变化;当i >= 指定periods时,固定用指定的periods计算。

方法一:向量化简洁实现

利用索引的clip方法快速生成每个位置对应的期数,再结合shift和除法模拟pct_change的逻辑(pct_change本质是(当前值 / 前n期值) - 1):

import pandas as pd

s = pd.Series([90, 91, 85, 95])
target_periods = 2  # 你需要的目标期数,比如365

# 生成每个位置对应的计算期数:小于target_periods的用索引值,大于等于的用target_periods
calc_periods = s.index.clip(upper=target_periods)

# 计算百分比变化
result = (s / s.shift(calc_periods)) - 1

# 可选:将第0位的NaN替换为0(对应第二种需求结果)
# result = result.fillna(0)

print(result)

运行结果(不替换NaN):

0         NaN
1    0.011111
2   -0.055556
3    0.043956
dtype: float64

方法二:numpy条件判断实现

如果需要更直观的逻辑控制,可以用numpy.where分情况处理:

import pandas as pd
import numpy as np

s = pd.Series([90, 91, 85, 95])
target_periods = 2

# 分情况计算:索引小于target_periods时用索引作为期数,否则用target_periods
result = np.where(
    s.index < target_periods,
    (s / s.shift(s.index)) - 1,
    (s / s.shift(target_periods)) - 1
)

# 转换为Series
result = pd.Series(result, index=s.index)

# 可选:将第0位设为0
# result.iloc[0] = 0

print(result)

补充说明

pct_change没有类似rolling的min_periods参数,是因为它的设计逻辑是固定对比n期前的单一值,而rolling是基于窗口内的聚合计算,两者的核心逻辑不同。我们的自定义方法本质是动态调整对比的基准值位置,正好满足你“逐步递增到目标期数”的需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 09:08:13