在给定条件表达式pandas的情况下找到最大的滚动窗口

时间:2019-01-18 20:28:19

标签: python pandas

在给定条件的情况下,我正在寻找列表中最大的窗口,并从我的数据框中返回这些特定记录。我有一个人,然后是他们完成的一项活动,我按时间顺序排序,发现他们的活动之间有几秒钟的差异。然后我想找到最大的连续部分,其中每个活动都在给定的秒数内

我创建了一个函数return max segment:

def return_max_segment(list_, max_seconds):
    counter = 0
    results = [0]
    for x in list_:
        if x <= max_seconds:
            counter += 1
            results.append(counter)
        else:
            counter = 0
    if len(results) == 0:
        final = 0
    else:
        final = max(results)
    return final

初始化数据:

def rand_date(x, y):
    return datetime.datetime(2018, 9, 20, 5, x, y)

random.seed(123)
dates = [rand_date(random.randint(0, 59), random.randint(0, 59)) for x in range(100)]
person = [random.choice(['005', '088']) for x in range(100)]
ids = range(100)

df = pd.DataFrame({'id':ids,
                   'person':person,
                   'activitydate':dates})

看一下df的头部:

   id person        activitydate
0   0    088 2018-09-20 05:03:17
1   1    005 2018-09-20 05:05:49
2   2    005 2018-09-20 05:26:17
3   3    088 2018-09-20 05:06:53
4   4    005 2018-09-20 05:57:55

到目前为止,到目前为止,我已经对数据帧进行分组以返回最大段。我陷入了如何获取此最大段引用的特定记录的问题,因为我需要记录id

dfg = df.groupby('person')['activitydate'] \
         .apply(lambda x: return_max_segment([y.seconds for y in x.sort_values().diff()[1:]], 50)) \
         .reset_index(drop=False)

  person  activitydate
0    005             4
1    088             8

005的记录中有4个连续记录的段,每个记录之间的间隔都在50秒之内。我想退还这4条记录。与008

相同

1 个答案:

答案 0 :(得分:0)

这是一种针对您的情况的方法。首先,我们将由一个人进行说明。

gb = df.groupby('person')
group5 = gb.get_group('005')
sorted_by_date = group5.sort_values('activitydate').reset_index(drop=True)
sorted_by_date['date_diff'] = sorted_by_date.activitydate.diff()
run_groups = sorted_by_date.groupby(
   (sorted_by_date.date_diff >= pd.Timedelta('50 seconds')).cumsum()
)
run_groups.get_group(run_groups.id.count().idxmax())

给出

    id person        activitydate date_diff  run_count
99  99    005 2018-09-20 05:40:10  00:01:30          0
68  68    005 2018-09-20 05:40:18  00:00:08          1
92  92    005 2018-09-20 05:40:25  00:00:07          2
82  82    005 2018-09-20 05:40:26  00:00:01          3
48  48    005 2018-09-20 05:41:11  00:00:45          4

棘手的部分是sorted_by_date.groupby((sorted_by_date.date_diff >= pd.Timedelta('50 seconds')).cumsum()),这是我在this great answer中发现的“ compare-cumsum-groupby模式”。换句话说,这将创建一个布尔列,其中False表示活动之间的差很短,然后获取该列的累加总和,以便在出现短暂差时,总和没有变化,然后按那笔钱。然后我们找到人数最多的组。

现在将其立即应用于所有人:

def get_longest_short_activity_run_length(group):
    sorted_by_date = group.sort_values('activitydate')
    sorted_by_date['date_diff'] = sorted_by_date.activitydate.diff()
    run_groups = sorted_by_date.groupby(
       (sorted_by_date.date_diff >= pd.Timedelta('50 seconds')).cumsum()
    )
    return run_groups.get_group(run_groups.id.count().idxmax())

gb.apply(get_longest_short_activity_run_length)

返回

           id person        activitydate date_diff
person                                            
005    99  99    005 2018-09-20 05:40:10  00:01:30
       68  68    005 2018-09-20 05:40:18  00:00:08
       92  92    005 2018-09-20 05:40:25  00:00:07
       82  82    005 2018-09-20 05:40:26  00:00:01
       48  48    005 2018-09-20 05:41:11  00:00:45
088    36  36    088 2018-09-20 05:00:25       NaT
       59  59    088 2018-09-20 05:01:12  00:00:47
       24  24    088 2018-09-20 05:01:18  00:00:06
       93  93    088 2018-09-20 05:01:20  00:00:02
       98  98    088 2018-09-20 05:01:40  00:00:20
       76  76    088 2018-09-20 05:02:00  00:00:20
       95  95    088 2018-09-20 05:02:48  00:00:48
       0    0    088 2018-09-20 05:03:17  00:00:29
       17  17    088 2018-09-20 05:04:00  00:00:43