pandas.Rolling中'on'参数作用及滚动窗口排序疑问
关于pandas rolling窗口与on参数的疑问解答
问题背景
用户的示例代码与数据:
import pandas as pd df = pd.DataFrame({"values": [3,2,1,1000,1,3,1],"day":[1,2,3,1,2,3,1]})
输出的初始DataFrame:
values day 0 3 1 1 2 2 2 1 3 3 1000 1 4 1 2 5 3 3 6 1 1
需求为:找出连续2个同day分组的最大值。
用户尝试两种方法后出现困惑:
- 先按
day排序再执行滚动:df.sort_values("day").rolling(2).sum().sort_index()得到预期结果 - 使用
on参数执行滚动:df.rolling(2,on="day").max()结果不符合预期,输出如下:
values day 0 NaN 1.0 1 3.0 2.0 2 2.0 3.0 3 1000.0 1.0 4 1000.0 2.0 5 3.0 3.0 6 3.0 1.0
核心原因解析
1. rolling窗口的本质是按行的物理位置滑动
不管是否使用on参数,rolling窗口都是基于DataFrame的当前行顺序来滑动的,不会自动对数据做排序或分组。
排序后生效的原因是:排序操作将同day的行连续排列,此时rolling(2)会把相邻的同day数据纳入同一个窗口,自然能计算出同day连续两个数据的聚合结果。
2. on参数的真实作用
pandas文档中on参数的描述容易产生误解,它的真实功能是:
- 仅用于确定窗口的数值/时间边界(比如时间序列中按固定日期间隔划分窗口),而非帮你对数据分组或排序。
- 当指定
on="day"时,pandas会基于day列的值判断窗口是否符合大小要求,但不会改变原有行的顺序。例如原数据中行0(day1)与行3(day1)物理上不相邻,rolling(2,on="day")不会将这两行放入同一个窗口。
3. 排序后索引未变但生效的原因
df.sort_values("day")仅改变了行的物理排列顺序,索引虽然保留原值,但rolling窗口的滑动逻辑只关心当前行的先后顺序,与索引本身的数值无关。排序后原索引0、3、6的行被连续排列,rolling(2)会依次计算这三行中相邻两行的最大值,最后sort_index()只是将行序恢复为原索引顺序而已。
推荐实现方式
如果需要按day分组后每组内做滚动窗口计算,更准确的写法是结合groupby与rolling:
# 按day分组,每组内计算2个数据的滚动最大值 df["rolling_max"] = df.groupby("day")["values"].rolling(2).max().reset_index(level=0, drop=True)
内容的提问来源于stack exchange,提问作者guillaume V
相关产品推荐
相关产品推荐

