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