繁体   English   中英

在 Pandas 中的 GroupBy 内检查负滚动窗口中的条件

[英]Checking condition in negative rolling window within GroupBy in Pandas

以下是我的数据框的样子。 Expected_Output列是我想要的/目标列。

   Group  Value  Expected_Output
0      1      2                1
1      1      3                1
2      1      6                1
3      1     11                0
4      1      7                0
5      2      3                1
6      2     13                1
7      2     14                0

对于给定的Group ,从给定的行开始,我正在查看接下来的5 行并检查是否有任何Value > 10 如果为真,那么我想在Expected_Output返回 1,否则返回 0。

例如,在Group 1 ,从第一行开始, Value 11(大于 10)出现在 3 行内,并且确实落在满足条件的“下 5 行窗口”内,因此返回 1在Expected_Output Group 2的第 6 行类似, Value 14(大于 10)出现在 1 行内,并且确实落在满足条件的“下 5 行窗口”内,因此在Expected_Output返回 1。

我试过df.groupby('Group')['Value'].rolling(-5).max() > 10无济于事。

默认情况下, pd.Series.rolling向后看。 若要向前看,可以反转数据框,然后反转GroupBy结果。 您需要包括一个shift因为您正在寻找下一个 5个值。

def roller(x):
    return x.rolling(window=5, min_periods=1)['Value'].max().shift().gt(10).astype(int)

df['Result'] = df.iloc[::-1].groupby('Group', sort=False).apply(roller).iloc[::-1].values

print(df)

   Group  Value  Result
0      1      2       1
1      1      3       1
2      1      6       1
3      1     11       0
4      1      7       0
5      2      3       1
6      2     13       1
7      2     14       0

您可以尝试对数据帧进行分组,并利用数据帧索引来获取下一个可能的5个值,并检查是否有大于10的任何值

df['Expected_Output'] =df.groupby(['Group'])['Value'].transform(lambda y:list(map(lambda x: 1 if any(y.loc[set(np.arange(x+1,x+6)).intersection(y.index)] >10) else 0,y.index)))

出:

    Group   Value   Expected_Output
0   1   2   1
1   1   3   1
2   1   6   1
3   1   11  0
4   1   7   0
5   2   3   1
6   2   13  1
7   2   14  0

有一种方法可以在没有任何额外技巧的情况下做到这一点,但它需要您有一个排序维度。 与大多数时间序列数据一样,您应该拥有可用的时间变量。 那么解决方法很简单:

  1. 向后排序
  2. 使用标准的.rolling(window)功能
  3. (可选)再次排序

示例:睡眠研究

from pydataset import data
sleep_study = data('sleepstudy')
print(sleep_study.head(5))
   Reaction  Days  Subject
1  249.5600     0      308
2  258.7047     1      308
3  250.8006     2      308
4  321.4398     3      308
5  356.8519     4      308

1)向后排序

sleep_study.sort_values(by=['Subject', 'Days'], ascending=False, inplace=True)

2) 使用.rolling(window)

sleep_study['max_react_next_3_days'] = sleep_study\
    .groupby('Subject')['Reaction']\
    .rolling(window=3, min_periods=1, closed='left').max()\
    .droplevel(level=0)
sleep_study['expected_output'] = sleep_study['max_react_next_3_days'] > 400

解释:

  • 我们要向前看 3 天,因此window=3
  • 但是,研究中只剩下 2 或 1 天也可以,所以min_periods=1 -- 这取决于您的假设/喜好
  • 我们想使用接下来的3 天,而不是当天,所以我们使用closed='left'排除它,这意味着rolling需要一个半开区间,在“右边”打开,在“左边”关闭”。

3)再次排序,以免有意外

sleep_study.sort_values(by=['Subject', 'Days'], ascending=True, inplace=True)

结果:

print(sleep_study.head(20))
    Reaction  Days  Subject  max_react_next_3_days  expected_output
1   249.5600     0      308               321.4398            False
2   258.7047     1      308               356.8519            False
3   250.8006     2      308               414.6901             True
4   321.4398     3      308               414.6901             True
5   356.8519     4      308               414.6901             True
6   414.6901     5      308               430.5853             True
7   382.2038     6      308               466.3535             True
8   290.1486     7      308               466.3535             True
9   430.5853     8      308               466.3535             True
10  466.3535     9      308                    NaN            False
11  222.7339     0      309               205.2658            False
12  205.2658     1      309               207.7161            False
13  202.9778     2      309               215.9618            False
14  204.7070     3      309               215.9618            False
15  207.7161     4      309               217.7272            False
16  215.9618     5      309               224.2957            False
17  213.6303     6      309               237.3142            False
18  217.7272     7      309               237.3142            False
19  224.2957     8      309               237.3142            False
20  237.3142     9      309                    NaN            False

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM