基于日期边界拆分DataFrame跨日期单行记录
拆分跨日期的DataFrame记录
完整实现代码
import pandas as pd # 原始数据 df = pd.DataFrame({'ID': [1, 2], 'Start': ['2022-01-28 20:30:03', '2022-01-29 04:19:07'], 'End': ['2022-01-29 03:29:55', '2022-01-31 08:37:59']}) # 转换时间列为datetime类型 df['Start'] = pd.to_datetime(df['Start']) df['End'] = pd.to_datetime(df['End']) # 定义单行拆分逻辑 def split_cross_day(row): start_date = row['Start'].date() end_date = row['End'].date() # 日期相同直接返回原行 if start_date == end_date: return pd.DataFrame([row]) # 生成所有涉及的日期序列 date_range = pd.date_range(start=start_date, end=end_date) rows = [] # 处理第一天:保留起始时间,结束为当日23:59:59 first_row = row.copy() first_row['End'] = pd.Timestamp(start_date) + pd.Timedelta(days=1) - pd.Timedelta(seconds=1) rows.append(first_row) # 处理中间日期(若存在):当日00:00:00到23:59:59 for date in date_range[1:-1]: mid_row = row.copy() mid_row['Start'] = pd.Timestamp(date) mid_row['End'] = pd.Timestamp(date) + pd.Timedelta(days=1) - pd.Timedelta(seconds=1) rows.append(mid_row) # 处理最后一天:起始为当日00:00:00,保留原结束时间 last_row = row.copy() last_row['Start'] = pd.Timestamp(end_date) rows.append(last_row) return pd.DataFrame(rows) # 应用拆分逻辑并合并结果 result_df = pd.concat(df.apply(split_cross_day, axis=1).tolist(), ignore_index=True) # 可选:转换为字符串格式便于查看 result_df['Start'] = result_df['Start'].dt.strftime('%Y-%m-%d %H:%M:%S') result_df['End'] = result_df['End'].dt.strftime('%Y-%m-%d %H:%M:%S') print(result_df)
关键步骤说明
- 时间类型转换:必须先将
Start和End列从字符串转为datetime类型,才能进行日期提取、时间计算等操作。 - 单行拆分逻辑:
- 先判断当前行的起始和结束日期是否相同,相同则无需拆分。
- 生成所有覆盖的日期范围,比如跨3天的记录会生成3个日期节点。
- 分三段处理:第一天保留原起始时间,结束为当日23:59:59;中间日期用全天时间范围;最后一天保留原结束时间,起始为当日00:00:00。
- 结果合并:通过
df.apply逐行执行拆分函数,将返回的多个小DataFrame用pd.concat合并,最后重置索引得到最终结果。
内容的提问来源于stack exchange,提问作者MBlankfield
相关产品推荐
相关产品推荐

