简体   繁体   English

Python:Pandas,如何 select 行在 groupby 之后的不同日期范围内

[英]Python: Pandas, how to select rows that in different ranges of date after groupby

I have a dataframe like this:我有一个像这样的 dataframe:

    ID  Date        Value
0   A   2018-01-01  -1.452486
1   A   2018-01-02  -0.554813
2   A   2018-01-03  0.710189
3   A   2018-01-04  1.980976
4   A   2018-01-05  1.586007
... ... ... ...
1090    C   2018-12-27  0.020119
1091    C   2018-12-28  -0.720705
1092    C   2018-12-29  -0.124303
1093    C   2018-12-30  0.921005
1094    C   2018-12-31  0.073129

Each group of ID has a row that value is 100:每组 ID 有一行value 100:

    ID  Date        Value
54  A   2018-02-24  100.0
554 B   2018-07-09  100.0
854 C   2018-05-05  100.0

Now I want to select a subset of the dataframe that based on its Date whose value is 100 and backward 2 weeks:现在我想 select dataframe 的一个子集,它基于其value 100 和向后 2 周的Date

    ID  Date        Value
41  A   2018-02-11  0.841923
42  A   2018-02-12  -1.116607
43  A   2018-02-13  0.560046
44  A   2018-02-14  -0.359288
45  A   2018-02-15  2.091080
46  A   2018-02-16  -0.827285
47  A   2018-02-17  0.061536
48  A   2018-02-18  0.536367
49  A   2018-02-19  0.379075
50  A   2018-02-20  0.442490
51  A   2018-02-21  -0.461630
52  A   2018-02-22  0.496318
53  A   2018-02-23  1.478587
54  A   2018-02-24  100.000000
541 B   2018-06-26  -0.425352
542 B   2018-06-27  0.489837
543 B   2018-06-28  2.421981
544 B   2018-06-29  2.068240
545 B   2018-06-30  0.733924
546 B   2018-07-01  -0.505563
547 B   2018-07-02  -0.199901
548 B   2018-07-03  1.116411
549 B   2018-07-04  -0.652445
550 B   2018-07-05  2.327285
551 B   2018-07-06  0.443507
552 B   2018-07-07  0.227356
553 B   2018-07-08  -0.951611
554 B   2018-07-09  100.000000
841 C   2018-04-22  -0.214560
842 C   2018-04-23  1.189581
843 C   2018-04-24  0.375965
844 C   2018-04-25  1.721489
845 C   2018-04-26  0.819428
846 C   2018-04-27  -0.777456
847 C   2018-04-28  -0.560471
848 C   2018-04-29  -0.437284
849 C   2018-04-30  -0.786168
850 C   2018-05-01  0.780642
851 C   2018-05-02  -0.634718
852 C   2018-05-03  1.541415
853 C   2018-05-04  -0.905156
854 C   2018-05-05  100.000000

I have tried groupby() , filter() and between_time() but could not get the desired output.我已经尝试过groupby()filter()between_time()但无法获得所需的 output。

Here is the input dateframe of above:这是上面的输入日期框:

from itertools import chain
import random
import pandas as pd
import numpy as np

df_1 = pd.DataFrame({
        'ID' : list(chain.from_iterable([['A'] * 365, ['B'] * 365, ['C'] * 365])),
        'Date' : pd.date_range(start = '2018-01-01', end = '2018-12-31').tolist() + pd.date_range(start = '2018-01-01', end = '2018-12-31').tolist() + pd.date_range(start = '2018-01-01', end = '2018-12-31').tolist(),
        'Value' : np.random.randn(365 * 3)
        })

df_1.iloc[54, 2] = 100
df_1.iloc[554, 2] = 100
df_1.iloc[854, 2] = 100

Thanks for the help!谢谢您的帮助!

Using GroupBy.apply and then finding the row which has Value 100 and using pd.DateOffset to get the rows between 2 weeks before:使用GroupBy.apply然后找到具有Value 100的行并使用pd.DateOffset获取两周前的行:

df_1.groupby('ID')\
    .apply(lambda x: x.loc[x['Date']\
                           .between(x.loc[x['Value'].eq(100), 'Date'].iat[0]-pd.DateOffset(weeks=2), 
                                    x.loc[x['Value'].eq(100), 'Date'].iat[0])]).reset_index(drop=True)

Or more readable in a function:或者在 function 中更具可读性:

def get_rows(x):
    date = x.loc[x['Value'].eq(100), 'Date'].iat[0]
    newdata = x.loc[x['Date'].between(date-pd.DateOffset(weeks=2), date)]

    return newdata

grp = df_1.groupby('ID').apply(get_rows).reset_index(drop=True)

Output Output

   ID       Date       Value
0   A 2018-02-10    1.493770
1   A 2018-02-11    1.141011
2   A 2018-02-12    0.169845
3   A 2018-02-13    0.978423
4   A 2018-02-14    0.685567
5   A 2018-02-15   -0.268094
6   A 2018-02-16   -0.256714
7   A 2018-02-17   -1.565485
8   A 2018-02-18    2.889279
9   A 2018-02-19    0.236144
10  A 2018-02-20    0.484225
11  A 2018-02-21   -1.244975
12  A 2018-02-22   -0.476240
13  A 2018-02-23    0.744125
14  A 2018-02-24  100.000000
15  B 2018-06-25   -1.256417
16  B 2018-06-26   -0.392734
17  B 2018-06-27   -0.615133
18  B 2018-06-28   -0.410776
19  B 2018-06-29   -2.246637
20  B 2018-06-30   -0.389098
21  B 2018-07-01    0.257526
22  B 2018-07-02   -0.865095
23  B 2018-07-03    1.165467
24  B 2018-07-04    0.914455
25  B 2018-07-05    0.306181
26  B 2018-07-06   -0.903388
27  B 2018-07-07   -1.244789
28  B 2018-07-08    0.526398
29  B 2018-07-09  100.000000
30  C 2018-04-21    1.370516
31  C 2018-04-22    0.207436
32  C 2018-04-23    1.087256
33  C 2018-04-24   -1.031925
34  C 2018-04-25   -0.279739
35  C 2018-04-26   -0.627787
36  C 2018-04-27   -0.149531
37  C 2018-04-28    0.237061
38  C 2018-04-29   -0.756877
39  C 2018-04-30   -0.855831
40  C 2018-05-01   -0.864244
41  C 2018-05-02   -1.159661
42  C 2018-05-03   -1.430411
43  C 2018-05-04    0.708505
44  C 2018-05-05  100.000000

You can use groupby and apply a lamdba function that grabs the Value==100 element and backtracks 14 days.您可以使用 groupby 并应用 lamdba function 来获取 Value==100 元素并回溯 14 天。

df_1.groupby('ID').apply(lambda g: g.loc[
    g.Date.gt(g.query('Value==100').Date.iloc[0] - pd.Timedelta(14, 'D'))
    & g.Date.le(g.query('Value==100').Date.iloc[0])
]).reset_index(level=0, drop=True)
# returns:
    ID       Date       Value
41   A 2018-02-11   -0.974209
42   A 2018-02-12    0.090468
43   A 2018-02-13    0.052444
44   A 2018-02-14    0.070550
45   A 2018-02-15   -0.989467
46   A 2018-02-16    0.355879
47   A 2018-02-17   -0.480722
48   A 2018-02-18   -0.631650
49   A 2018-02-19   -0.683452
50   A 2018-02-20    1.285355
51   A 2018-02-21    1.377012
52   A 2018-02-22    0.544838
53   A 2018-02-23    0.118181
54   A 2018-02-24  100.000000
541  B 2018-06-26    1.012775
542  B 2018-06-27    0.543416
543  B 2018-06-28   -0.071764
544  B 2018-06-29   -0.828533
545  B 2018-06-30   -0.082200
546  B 2018-07-01    1.260128
547  B 2018-07-02    0.936050
548  B 2018-07-03    1.861192
549  B 2018-07-04   -0.299974
550  B 2018-07-05    0.841579
551  B 2018-07-06   -0.218278
552  B 2018-07-07   -0.757397
553  B 2018-07-08    0.928673
554  B 2018-07-09  100.000000
841  C 2018-04-22   -1.148765
842  C 2018-04-23   -0.496060
843  C 2018-04-24    0.559782
844  C 2018-04-25    0.913943
845  C 2018-04-26    0.027123
846  C 2018-04-27    1.474957
847  C 2018-04-28    1.352606
848  C 2018-04-29   -1.324069
849  C 2018-04-30    0.165570
850  C 2018-05-01    0.771027
851  C 2018-05-02   -0.568807
852  C 2018-05-03    1.581479
853  C 2018-05-04    0.999872
854  C 2018-05-05  100.000000

With the following structure you get the breakpoints where the value 100 is present in your dataframe.通过以下结构,您可以获得 dataframe 中存在值 100 的断点。

for x,i in zip(df_1['Value'] == 100,df_1.index):

  if x:#boolean True if Value = 100

    two_weeks = (i-15)
    print(df_1.iloc[two_weeks:i])

        ID       Date     Value
    39  A 2018-02-09  1.405063
    40  A 2018-02-10 -0.885830
    41  A 2018-02-11 -0.618240
    42  A 2018-02-12  0.189675
    43  A 2018-02-13 -1.128798
    44  A 2018-02-14 -0.847795
    45  A 2018-02-15 -0.548889
    46  A 2018-02-16 -0.672275
    47  A 2018-02-17  1.402386
    48  A 2018-02-18  1.559774
    49  A 2018-02-19  0.496039
    50  A 2018-02-20  0.172402
    51  A 2018-02-21 -0.260821
    52  A 2018-02-22  1.099741
    53  A 2018-02-23  0.917311
        ID       Date     Value
    539  B 2018-06-24  0.148511
    540  B 2018-06-25  0.975276
    541  B 2018-06-26  0.874365
    542  B 2018-06-27 -0.143335
    543  B 2018-06-28  1.011093
    544  B 2018-06-29  0.180327
    545  B 2018-06-30  1.629272
    546  B 2018-07-01 -0.876905
    547  B 2018-07-02  0.450003
    548  B 2018-07-03  0.338859
    549  B 2018-07-04 -1.590210
    550  B 2018-07-05 -0.659832
    551  B 2018-07-06  0.187246
    552  B 2018-07-07  0.503597
    553  B 2018-07-08 -0.378273
        ID       Date     Value
    839  C 2018-04-20  0.597722
    840  C 2018-04-21 -1.407209
    841  C 2018-04-22  1.339154
    842  C 2018-04-23 -1.070049
    843  C 2018-04-24  2.104513
    844  C 2018-04-25 -0.242507
    845  C 2018-04-26 -0.313100
    846  C 2018-04-27  0.579189
    847  C 2018-04-28  0.812848
    848  C 2018-04-29  0.288989
    849  C 2018-04-30  1.092859
    850  C 2018-05-01  0.509114
    851  C 2018-05-02  0.151621
    852  C 2018-05-03  0.635293
    853  C 2018-05-04  0.768101

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

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