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

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

代码说明

  1. df['Result'][1:]:跳过索引0,获取从索引1到9的Result数据,这正是我们需要分配给前序索引的窗口数据源
  2. rolling(window=window_size, min_periods=1):对后续数据计算滚动窗口众数,min_periods=1确保窗口长度不足4时仍能计算
  3. pd.concat(...):将滚动结果对齐到原DataFrame的索引0-8,索引9补NaN(因为没有后续4个元素)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:56:08