You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas DataFrame中拆分跨午夜的时间区间行

拆分Pandas DataFrame中跨午夜的时间区间

嘿,这个需求我之前处理过,其实用Pandas就能轻松搞定!咱们先从重现你的数据开始,然后一步步实现拆分逻辑,最后还会给你一个高效的优化方案。

首先,先把你给的数据构造代码贴出来,方便大家复现:

import pandas as pd

# 生成原始DataFrame
df = pd.DataFrame(data=pd.date_range('20100201', periods=10, freq='5h3min'), columns=['Start'])
df['End'] = df['Start'] + pd.Timedelta(4, 'h')

核心思路

我们的目标是:找出所有Start和End不在同一天的行(也就是跨午夜的区间),把它们拆成两段:

  1. 第一段从原Start到当天的最后一刻(比如23:59:59,或者你示例里的23:59:00,这个可以调整)
  2. 第二段从次日的00:00:00到原End

方案一:直观的循环实现(适合小数据集)

这种方式逻辑清晰,新手也能一眼看懂:

# 先标记哪些行需要拆分
df['cross_midnight'] = df['Start'].dt.date != df['End'].dt.date

# 用来存储拆分后的所有行
split_rows = []

# 遍历每一行处理
for _, row in df.iterrows():
    if row['cross_midnight']:
        # 计算当天的结束时间(这里用当天最后一秒,要改成23:59:00就换成pd.Timedelta(minutes=1))
        day_end = row['Start'].normalize() + pd.Timedelta(days=1) - pd.Timedelta(seconds=1)
        # 添加第一段
        split_rows.append({'Start': row['Start'], 'End': day_end})
        # 计算次日的开始时间
        next_day_start = row['Start'].normalize() + pd.Timedelta(days=1)
        # 添加第二段
        split_rows.append({'Start': next_day_start, 'End': row['End']})
    else:
        # 不需要拆分的行直接加入
        split_rows.append(row[['Start', 'End']].to_dict())

# 转换成新的DataFrame并重置索引
new_df = pd.DataFrame(split_rows).reset_index(drop=True)

# 打印结果看看
print(new_df)

运行后,你会看到原数据中跨午夜的行被成功拆分,和你给出的示例效果一致~


方案二:向量化优化(适合大数据集)

如果你的数据量很大,循环的效率就不够看了,咱们用Pandas的向量化操作来提速:

import pandas as pd

# 还是先构造原始数据
df = pd.DataFrame(data=pd.date_range('20100201', periods=10, freq='5h3min'), columns=['Start'])
df['End'] = df['Start'] + pd.Timedelta(4, 'h')

# 筛选出需要拆分的行
cross_df = df[df['Start'].dt.date != df['End'].dt.date].copy()

# 生成拆分后的第一部分(到当天结束)
cross_part1 = cross_df.assign(End=cross_df['Start'].dt.normalize() + pd.Timedelta(days=1) - pd.Timedelta(seconds=1))
# 生成拆分后的第二部分(次日开始)
cross_part2 = cross_df.assign(Start=cross_df['Start'].dt.normalize() + pd.Timedelta(days=1))

# 合并不需要拆分的行 + 拆分后的两部分
new_df = pd.concat(
    [df[df['Start'].dt.date == df['End'].dt.date], cross_part1, cross_part2],
    ignore_index=True
)

# 按Start时间重新排序(保证顺序和原数据一致)
new_df = new_df.sort_values('Start').reset_index(drop=True)

print(new_df)

这种方式完全不用循环,利用Pandas的批量处理能力,速度能提升好几倍,处理十万级以上的数据也毫无压力。


小调整:匹配你示例中的23:59:00

如果你想和示例一样把当天结束时间设为23:59:00,只需要把计算day_end的代码改成:

day_end = row['Start'].normalize() + pd.Timedelta(days=1) - pd.Timedelta(minutes=1)

这样就完美匹配你的输出要求啦!

内容的提问来源于stack exchange,提问作者00__00__00

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:46:00