在使用rolling()获取最大值时,是否可以排除每个窗口的前n个值?

2 投票
1 回答
37 浏览
提问于 2025-04-14 17:29

这是我的数据表:

import pandas as pd
df = pd.DataFrame({'a': [150, 106, 119, 131, 121, 140, 160, 119, 170]})

这是我期望的输出结果。我想创建一列 b

     a      b
0  150      140
1  106      160
2  119      160
3  131      161 
4  121      NaN
5  140      NaN
6  160      NaN
7  119      NaN
8  170      NaN

我想在一个6个数据的窗口中找到最大值。不过,我希望忽略每个窗口的第一个值。

在这张图片中,我展示了我想要的窗口。红色的单元格是要排除在计算之外的,而绿色的单元格是窗口中的最大值,这些最大值会放在 b 列里。

在这里输入图片描述

我希望有一个通用的解决方案。比如说,在忽略每个窗口的前N个值后再获取 max()

以下是我尝试过但没有成功的一些方法:

# attempt 1
df['b'] = df.a.shift(-1).rolling(6).max()
# attempt 2
df['b'] = df.a.rolling(6, closed='left').max()
# attempt 3 
for i in range(3):
    x = df.iloc[i+1:i+6]

1 个回答

3

简单的方法是使用 groupby.transform,然后把第一个值去掉:

N = 6
df['out'] = df.loc[::-1, 'a'].rolling(N).apply(lambda x: x.iloc[:-1].max())

不过,因为你的操作和这个值没有关系,最好是在计算 rolling.max 时用 N-1,然后再用 shift。这样可以让代码更简单:

N = 6
df['out'] = df.loc[::-1, 'a'].rolling(N-1).max().shift()

注意,因为 rolling 默认使用的是之前的值,所以我们需要先用 [::-1]反转这个序列的顺序。

输出结果:

     a    out
0  150  140.0
1  106  160.0
2  119  160.0
3  131  170.0
4  121    NaN
5  140    NaN
6  160    NaN
7  119    NaN
8  170    NaN

推广

如果想要跳过 skip 的值,可以这样推广:

N = 6
skip = 2

df['out'] = df.loc[::-1, 'a'].rolling(N-skip).max().shift(skip)

举个例子(为了更清楚,把第二个 119 改成 118):

     a  skip=0  skip=1  skip=2  skip=3  skip=4  skip=5  skip=6
0  150   150.0   140.0   140.0   140.0   140.0   140.0     NaN
1  106   160.0   160.0   160.0   160.0   160.0   160.0     NaN
2  119   160.0   160.0   160.0   160.0   160.0   118.0     NaN
3  131   170.0   170.0   170.0   170.0   170.0   170.0     NaN
4  121     NaN     NaN     NaN     NaN     NaN     NaN     NaN
5  140     NaN     NaN     NaN     NaN     NaN     NaN     NaN
6  160     NaN     NaN     NaN     NaN     NaN     NaN     NaN
7  118     NaN     NaN     NaN     NaN     NaN     NaN     NaN
8  170     NaN     NaN     NaN     NaN     NaN     NaN     NaN

撰写回答