Pandas按连续相同Geofence分组 提取每组首入末出时间
问题背景
Python实现Geofence停留段统计时,直接按Geofence字段分组会将所有同名围栏合并,无法识别被其他围栏间隔开的独立停留段。
现有DataFrame包含Geofence、Time_in、Time_out、Total_time四个字段,样例数据如下:
Geofence Time_in Time_out Total_time 0 30TA 2022-07-12 20:34:07 2022-07-12 20:44:36 0:10:29 1 KNS 2022-07-12 20:47:08 2022-07-12 20:51:39 0:04:31 2 KNS 2022-07-12 20:52:09 2022-07-12 20:54:37 0:02:28 3 KNS 2022-07-12 21:04:38 2022-07-12 21:24:40 0:20:02 4 30TA 2022-07-12 21:27:13 2022-07-12 21:33:13 0:06:00 5 KNS 2022-07-12 21:37:14 2022-07-12 22:00:16 0:23:02 6 30TA 2022-07-12 22:02:44 2022-07-12 22:19:48 0:17:04 7 KNS 2022-07-12 22:22:19 2022-07-12 22:44:49 0:22:30 8 30TA 2022-07-12 22:46:49 2022-07-12 22:48:49 0:02:00 9 30TA 2022-07-12 22:50:22 2022-07-12 22:55:52 0:05:30 10 30TA 2022-07-12 22:56:23 2022-07-12 23:11:24 0:15:01 11 KNS 2022-07-12 23:13:54 2022-07-12 23:39:27 0:25:33 12 30TA 2022-07-12 23:41:27 2022-07-12 23:47:27 0:06:00
需求规则
- 按连续相同的Geofence值划分停留组:例如索引1-3行连续为KNS属于同一组,后续出现的KNS如果中间间隔了30TA记录,则单独划分为新组
- 每个分组提取3个字段:
- Geofence围栏名称
- 组内第一条记录的
Time_in(进入围栏时间) - 组内最后一条记录的
Time_out(离开围栏时间)
- 最终输出仅包含
Geofence、Time_in、Time_out三列的汇总DataFrame
原有错误实现
直接使用groupby(['Geofence'])会合并所有同名围栏,无法区分间断出现的独立停留段,代码如下:
import pandas as pd df = pd.read_excel(r'KNS_Night_Shift_GPS_Report_2022-07-15.xlsx', engine='openpyxl') df = df.loc[df['Grouping'] == 'XE3257X', ['Geofence', 'Time in', 'Time out']] for i, g in df.groupby(['Geofence']): print(g)
实现方案
核心思路是先为每一段连续相同的Geofence生成唯一分组ID,再基于该ID做聚合,避免合并非连续的同名围栏。
完整代码
import pandas as pd # 原有数据读取逻辑保持不变 df = pd.read_excel(r'KNS_Night_Shift_GPS_Report_2022-07-15.xlsx', engine='openpyxl') df = df.loc[df['Grouping'] == 'XE3257X', ['Geofence', 'Time in', 'Time out']] # 关键步骤:生成连续段分组ID # 当当前行Geofence和上一行不一致时,分组序号+1,相同则保持同组 df['stay_group_id'] = (df['Geofence'] != df['Geofence'].shift()).cumsum() # 按分组ID聚合,提取需要的字段 result = df.groupby('stay_group_id', as_index=False).agg( Geofence=('Geofence', 'first'), Time_in=('Time in', 'first'), Time_out=('Time out', 'last') ) print(result)
输出结果
基于提供的样例数据,运行后输出如下:
Geofence Time_in Time_out 0 30TA 2022-07-12 20:34:07 2022-07-12 20:44:36 1 KNS 2022-07-12 20:47:08 2022-07-12 21:24:40 2 30TA 2022-07-12 21:27:13 2022-07-12 21:33:13 3 KNS 2022-07-12 21:37:14 2022-07-12 22:00:16 4 30TA 2022-07-12 22:02:44 2022-07-12 22:19:48 5 KNS 2022-07-12 22:22:19 2022-07-12 22:44:49 6 30TA 2022-07-12 22:46:49 2022-07-12 23:11:24 7 KNS 2022-07-12 23:13:54 2022-07-12 23:39:27 8 30TA 2022-07-12 23:41:27 2022-07-12 23:47:27
逻辑说明
df['Geofence'].shift():将Geofence列向下错位1行,用于对比当前行和上一行的围栏值!=判断:当前后两行围栏值不同时返回True(等价于数值1),相同时返回False(等价于数值0)cumsum():对布尔值做累加,每遇到一次围栏变化,序号就加1,自然为每一段连续相同的围栏分配了唯一ID
内容的提问来源于stack exchange,提问作者JohnTan
相关产品推荐
相关产品推荐

