Pandas DataFrame滚动窗口众数投票结果分配问题求助
问题:将后续滚动窗口的众数分配到前序索引
现有数据与生成代码
生成目标DataFrame的代码如下:
import numpy as np import pandas as pd np.random.seed(0) df = pd.DataFrame({'Close': np.random.uniform(0, 100, size=10)}) lbound, ubound = 0, 1 change = df["Close"].diff() df["Change"] = change df["Result"] = np.select( [ np.isclose(change, 1) | np.isclose(change, 0) | np.isclose(change, -1), (change > 0) & (change > ubound), (change < 0) & (change < lbound), change.between(lbound, ubound) ], [0, 1, -1, 0] )
生成的原始数据:
Close Change Result 0 54.881350 NaN 0 1 71.518937 16.637586 1 2 60.276338 -11.242599 -1 3 54.488318 -5.788019 -1 4 42.365480 -12.122838 -1 5 64.589411 22.223931 1 6 43.758721 -20.830690 -1 7 89.177300 45.418579 1 8 96.366276 7.188976 1 9 38.344152 -58.022124 -1
需求说明
需要实现:
- 将索引1、2、3、4的
Result列众数分配给索引0 - 将索引2、3、4、5的
Result列众数分配给索引1 - 以此类推,每个索引
i对应索引i+1到i+4的Result列众数
尝试的代码及问题
尝试使用滚动窗口+shift的方式,但结果不符合预期:
df['Voting'] = df['Result'].rolling(window = 4,min_periods=1).apply(lambda x: x.mode()[0]).shift()
得到的错误结果:
Close Change Result Voting 0 54.881350 NaN 0 NaN 1 71.518937 16.637586 1 0.0 2 60.276338 -11.242599 -1 0.0 3 54.488318 -5.788019 -1 -1.0 4 42.365480 -12.122838 -1 -1.0 5 64.589411 22.223931 1 -1.0 6 43.758721 -20.830690 -1 -1.0 7 89.177300 45.418579 1 -1.0 8 96.366276 7.188976 1 -1.0 9 38.344152 -58.022124 -1 1.0
问题根源:默认的rolling窗口是向前回溯的(比如索引4的窗口是0-3),而我们需要的是向后展望的窗口(索引0对应1-4),直接shift无法对齐正确的窗口范围。
解决方案
通过提取后续数据计算滚动众数,再对齐到前序索引的方式实现:
window_size = 4 # 提取从索引1开始的Result列,计算滚动窗口众数 rolling_modes = df['Result'][1:].rolling(window=window_size, min_periods=1).apply( lambda x: x.mode()[0], raw=False ) # 将滚动结果对齐到原DataFrame的前9行,最后一行补NaN df['Voting'] = pd.concat([rolling_modes.reset_index(drop=True), pd.Series([np.nan])], ignore_index=True)
执行后得到的正确结果:
Close Change Result Voting 0 54.881350 NaN 0 -1.0 1 71.518937 16.637586 1 -1.0 2 60.276338 -11.242599 -1 -1.0 3 54.488318 -5.788019 -1 -1.0 4 42.365480 -12.122838 -1 1.0 5 64.589411 22.223931 1 -1.0 6 43.758721 -20.830690 -1 1.0 7 89.177300 45.418579 1 1.0 8 96.366276 7.188976 1 -1.0 9 38.344152 -58.022124 -1 NaN
代码说明
df['Result'][1:]:跳过索引0,获取从索引1到9的Result数据,这正是我们需要分配给前序索引的窗口数据源rolling(window=window_size, min_periods=1):对后续数据计算滚动窗口众数,min_periods=1确保窗口长度不足4时仍能计算pd.concat(...):将滚动结果对齐到原DataFrame的索引0-8,索引9补NaN(因为没有后续4个元素)
内容的提问来源于stack exchange,提问作者Raagib khan
相关产品推荐
相关产品推荐

