如何基于Pandas的开始、结束datetime列跨小时拆分生成新DataFrame
Pandas 实现跨小时时间区间拆分方案
完全可以通过Pandas实现你描述的需求,核心思路是先生成每条原记录时间范围内的所有小时整点分割边界,再基于边界把长区间切分为连续的小时粒度短区间,具体实现步骤如下:
前置准备
首先确保原DataFrame的开始、结束时间列为datetime格式,避免字符串类型计算报错:
# 强制转换时间列格式 df['start'] = pd.to_datetime(df['start']) df['end'] = pd.to_datetime(df['end'])
核心实现逻辑
- 对每条原记录,梳理出所有需要切割时间的小时整点位置:
- 先算原开始时间所在小时的终点(把开始时间向上取整到最近的整点,比如10:30取整就是11:00)作为第一个切割点
- 再算原结束时间所在的最近完整小时的终点(比如13:15向下取整到最近的整点就是13:00)作为最后一个切割点
- 两个切割点之间按1小时间隔生成所有整点,作为中间的切割线
- 如果原记录的开始和结束就在同一个小时里,无需切割,直接保留原行即可
- 顺着切割点把原来的长时间段切成一段段连续的短区间:
- 第一段从原开始时间走到第一个切割点
- 中间的每一段都是相邻两个切割点之间的完整小时区间
- 最后一段从最后一个切割点走到原记录的结束时间
- 把拆出来的多段时间从原来的嵌套结构里炸开成独立的行,原记录里除时间列外的其他字段直接对应填充到拆分后的新行中,保证和原表结构完全一致。
可复用代码
import pandas as pd def split_time_range_by_hour(df, start_col='start', end_col='end'): def get_split_segments(row): start = row[start_col] end = row[end_col] # 计算首尾分割边界 first_split = start.ceil('H') last_split = end.floor('H') # 同小时内直接返回原区间 if first_split > last_split: return ([start], [end]) # 生成所有小时分割点 split_points = pd.date_range(start=first_split, end=last_split, freq='H') # 拼接所有连续区间 seg_starts = [start] + split_points.tolist() seg_ends = split_points.tolist() + [end] return (seg_starts, seg_ends) # 应用分割逻辑 split_result = df.apply( lambda row: pd.Series( get_split_segments(row), index=['seg_start', 'seg_end'] ), axis=1 ) # 嵌套列表炸开为独立行 df_out = df.drop(columns=[start_col, end_col]).join( split_result.explode(['seg_start', 'seg_end']).reset_index(drop=True) ) # 重命名时间列对齐原结构 df_out = df_out.rename(columns={'seg_start': start_col, 'seg_end': end_col}) return df_out.reset_index(drop=True)
适配说明
- 方法自动支持跨自然日的拆分场景,不会因为日期跨天出现边界计算错误
- 若需要调整拆分粒度,只需把
freq='H'参数替换为对应粒度(比如'30min'为每30分钟拆分,'D'为按自然日拆分)即可 - 所有拆分后的区间完全连续无重叠,和原记录的总时间范围完全对齐,不会出现时间丢失或重叠的问题
内容的提问来源于stack exchange,提问作者Sunny
相关产品推荐
相关产品推荐

