如何在Pandas中基于values_1筛选存在时间重叠的行
解决Pandas按分组筛选时间重叠行的问题
需求说明
基于values_1列分组,仅保留同一分组内Start DateTime与End DateTime存在时间重叠的行;无重叠的分组直接移除,分组内无重叠的行也剔除。
实现方案
以下提供两种实现方式,分别适配小数据量和大数据量场景:
1. 基础循环实现(适合小数据量)
先构造示例DataFrame并确保时间列为datetime类型,再通过分组遍历判断重叠:
import pandas as pd # 构造示例数据 data = { 'values_1': ['VGM', 'VGM', 'VGM', 'WEH', 'WEH', 'WEH', 'POH', 'POH'], 'uniqId': [1278, 1259, 2567, 9854, 9124, 9785, 3479, 3449], 'DeptId': ['BKNG', 'BKNG', 'BKNG', 'ASKG', 'ASKG', 'ASKG', 'ASKG', 'ASKG'], 'Start DateTime': ['2023-09-05 18:35:28', '2023-09-05 18:55:18', '2023-09-05 14:29:38', '2023-09-05 13:45:58', '2023-09-05 17:25:28', '2023-09-05 16:15:21', '2023-09-05 15:35:29', '2023-09-05 17:35:28'], 'End DateTime': ['2023-09-05 20:05:28', '2023-09-05 19:25:38', '2023-09-05 17:35:28', '2023-09-05 15:00:00', '2023-09-05 19:43:13', '2023-09-05 18:24:02', '2023-09-05 17:25:22', '2023-09-05 18:35:19'] } df = pd.DataFrame(data) # 转换时间列为datetime类型(若未转换) df['Start DateTime'] = pd.to_datetime(df['Start DateTime']) df['End DateTime'] = pd.to_datetime(df['End DateTime']) def filter_overlapping(group): overlaps = [] for idx, row in group.iterrows(): # 计算当前行与组内所有行的重叠情况 mask = (group['Start DateTime'] < row['End DateTime']) & (group['End DateTime'] > row['Start DateTime']) # 排除自身,至少有一个其他行重叠则保留 has_overlap = mask.sum() > 1 overlaps.append(has_overlap) group['has_overlap'] = overlaps return group[group['has_overlap']] # 分组筛选并合并结果 result = df.groupby('values_1', group_keys=False).apply(filter_overlapping).drop('has_overlap', axis=1) print(result)
2. 向量化优化实现(适合大数据量)
利用Pandas的向量化操作替代循环,大幅提升处理效率:
def filter_overlapping_vectorized(group): # 生成时间矩阵,计算所有行对的重叠关系 starts = group['Start DateTime'].values[:, None] ends = group['End DateTime'].values[:, None] # 重叠条件:A的开始 < B的结束 且 B的开始 < A的结束 overlap_matrix = (starts < ends.T) & (starts.T < ends) # 每行是否有至少一个非自身的重叠行 has_overlap = overlap_matrix.sum(axis=1) > 1 return group[has_overlap] # 分组应用向量化筛选 result = df.groupby('values_1', group_keys=False).apply(filter_overlapping_vectorized) print(result)
输出结果
两种方式都会得到符合预期的DataFrame:
| values_1 | uniqId | DeptId | Start DateTime | End DateTime |
|---|---|---|---|---|
| VGM | 1278 | BKNG | 2023-09-05 18:35:28 | 2023-09-05 20:05:28 |
| VGM | 1259 | BKNG | 2023-09-05 18:55:18 | 2023-09-05 19:25:38 |
| WEH | 9124 | ASKG | 2023-09-05 17:25:28 | 2023-09-05 19:43:13 |
| WEH | 9785 | ASKG | 2023-09-05 16:15:21 | 2023-09-05 18:24:02 |
内容的提问来源于stack exchange,提问作者Tarak Pandya
相关产品推荐
相关产品推荐

