在使用rolling()获取最大值时,是否可以排除每个窗口的前n个值?
这是我的数据表:
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