Pandas非重叠时间序列调整算法实现求助
问题描述
我有一个包含start_datetime和end_datetime关键列的Pandas DataFrame,需实现如下逻辑:逐行与下一行比较,若当前行end_datetime晚于下一行start_datetime,则将下一行移至DataFrame末尾,重复操作直至形成无重叠的时间块,被移走的行作为新块的起始。我尝试用for循环解决,但受索引动态变化的问题困扰未完成,想知道是否有Pandas内置解决方案。
解决方案:无直接内置方法,但可用队列高效实现
Pandas没有直接对应此逻辑的内置函数,但可以用**队列(deque)**规避索引问题,比纯for循环更易维护且高效。核心思路是将行数据放入队列,逐个取出验证是否与当前块最后一行重叠:不重叠则加入当前块,重叠则放回队列尾部,直到队列清空,最终得到多个无重叠时间块。
代码实现
import pandas as pd from collections import deque def rearrange_time_blocks(df): # 复制原数据避免修改源DataFrame,重置索引消除原索引干扰 df_copy = df.copy().reset_index(drop=True) # 将行数据转为字典列表存入队列 queue = deque(df_copy.to_dict('records')) result_blocks = [] while queue: # 初始化新的时间块 current_block = [queue.popleft()] # 扩展当前块直到无法加入无重叠行 while queue: next_row = queue[0] # 检查当前块最后一行的结束时间是否早于下一行的开始时间 if current_block[-1]['end_datetime'] <= next_row['start_datetime']: current_block.append(queue.popleft()) else: # 重叠则将该行移至队列尾部 queue.append(queue.popleft()) # 将当前块转为DataFrame加入结果列表 result_blocks.append(pd.DataFrame(current_block)) return result_blocks
示例验证
输入示例
data = { 'start_datetime': pd.to_datetime(['2024-01-01 08:00', '2024-01-01 09:30', '2024-01-01 08:30', '2024-01-01 10:00']), 'end_datetime': pd.to_datetime(['2024-01-01 09:00', '2024-01-01 10:30', '2024-01-01 09:30', '2024-01-01 11:00']) } df = pd.DataFrame(data)
输出结果
函数返回两个无重叠的DataFrame块:
- 块1:
| start_datetime | end_datetime |
|---|---|
| 2024-01-01 08:00:00 | 2024-01-01 09:00:00 |
| 2024-01-01 09:30:00 | 2024-01-01 10:30:00 |
- 块2:
| start_datetime | end_datetime |
|---|---|
| 2024-01-01 08:30:00 | 2024-01-01 09:30:00 |
| 2024-01-01 10:00:00 | 2024-01-01 11:00:00 |
为什么不用纯for循环?
纯for循环会因行移动导致索引动态变化,需要手动维护索引逻辑,极易出错;而队列的popleft()和append()操作可自然处理行的转移,无需关注索引,代码简洁且逻辑清晰。
性能说明
队列实现的时间复杂度为O(n)(每行最多被取出和放回一次),远优于嵌套for循环的O(n²),适合处理较大规模的DataFrame。
内容的提问来源于stack exchange,提问作者MachineLearner
相关产品推荐
相关产品推荐

