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

如何在Pandas中为DataFrame添加累计时间的start_time和end_time列

问题描述

给定如下Pandas DataFrame:

import pandas as pd

df = pd.DataFrame([["X","0 min","30 mins"],["X","1 hour 1 min","20 mins"],["X","1 min","30 mins"],["X","41 mins","28 mins"],
                   ["Y","0 min","30 mins"],["Y","35 mins","25 mins"],["Y","1 hour 21 mins","30 mins"]],columns=["id","travel_time","dur"])

对应的表格:

idtravel_timedur
X0 min30 mins
X1 hour 1 min20 mins
X1 min30 mins
X41 mins28 mins
Y0 min30 mins
Y35 mins25 mins
Y1 hour 21 mins30 mins

需要新增start_time和end_time两列,规则如下:

  • 每个id的初始基准时间为9:00 AM
  • 每个id的首行start_time = 基准时间 + 当前行travel_time
  • 后续行start_time = 上一行的end_time + 当前行travel_time
  • end_time = 当前行start_time + 当前行dur

预期输出的DataFrame:

df_out = pd.DataFrame([["X","0 min","30 mins","9:00 AM","9:00 AM"],["X","1 hour 1 min","20 mins","10:01 AM","10:21 AM"],
                   ["X","1 min","30 mins","10:22 AM","10:52 AM"],["X","41 mins","28 mins","11:33 AM","12:01 PM"],
                   ["Y","0 min","30 mins","9:00 AM","9:00 AM"],["Y","35 mins","25 mins","9:35 AM","10:00 AM"],
                   ["Y","1 hour 21 mins","30 mins","11:21 AM","11:51 AM"]],columns=["id","travel_time","dur","start_time","end_time"])

对应的表格:

idtravel_timedurstart_timeend_time
X0 min30 mins9:00 AM9:00 AM
X1 hour 1 min20 mins10:01 AM10:21 AM
X1 min30 mins10:22 AM10:52 AM
X41 mins28 mins11:33 AM12:01 PM
Y0 min30 mins9:00 AM9:00 AM
Y35 mins25 mins9:35 AM10:00 AM
Y1 hour 21 mins30 mins11:21 AM11:51 AM
解决方案

步骤1:定义时间字符串转Timedelta的函数

先实现一个函数,把"1 hour 1 min"、"30 mins"这类字符串转换成Pandas可计算的Timedelta类型:

def str_to_timedelta(time_str):
    parts = time_str.split()
    hours = 0
    minutes = 0
    for i in range(0, len(parts), 2):
        val = int(parts[i])
        unit = parts[i+1]
        if 'hour' in unit:
            hours += val
        elif 'min' in unit:
            minutes += val
    return pd.Timedelta(hours=hours, minutes=minutes)

步骤2:转换时间列为Timedelta类型

将原始数据中的travel_time和dur列转换为Timedelta,方便后续时间运算:

df['travel_delta'] = df['travel_time'].apply(str_to_timedelta)
df['dur_delta'] = df['dur'].apply(str_to_timedelta)

步骤3:按id分组计算累计时间并生成目标列

以9:00 AM为基准时间,按id分组计算累计的行程时间,再推导start_time和end_time:

# 定义基准时间
base_time = pd.to_datetime('9:00 AM')

# 按id分组,累计计算行程时间
df['cum_travel'] = df.groupby('id')['travel_delta'].cumsum()

# 计算start_time并格式化输出
df['start_time'] = (base_time + df['cum_travel']).dt.strftime('%I:%M %p').str.lstrip('0')

# 计算end_time并格式化输出
df['end_time'] = (pd.to_datetime(df['start_time']) + df['dur_delta']).dt.strftime('%I:%M %p').str.lstrip('0')

步骤4:清理临时列,得到最终结果

删除中间过程中生成的临时列,保留需要的字段:

df_final = df[['id', 'travel_time', 'dur', 'start_time', 'end_time']]

完整代码

import pandas as pd

def str_to_timedelta(time_str):
    parts = time_str.split()
    hours = 0
    minutes = 0
    for i in range(0, len(parts), 2):
        val = int(parts[i])
        unit = parts[i+1]
        if 'hour' in unit:
            hours += val
        elif 'min' in unit:
            minutes += val
    return pd.Timedelta(hours=hours, minutes=minutes)

# 加载原始数据
df = pd.DataFrame([["X","0 min","30 mins"],["X","1 hour 1 min","20 mins"],["X","1 min","30 mins"],["X","41 mins","28 mins"],
                   ["Y","0 min","30 mins"],["Y","35 mins","25 mins"],["Y","1 hour 21 mins","30 mins"]],columns=["id","travel_time","dur"])

# 转换时间列
df['travel_delta'] = df['travel_time'].apply(str_to_timedelta)
df['dur_delta'] = df['dur'].apply(str_to_timedelta)

# 计算目标列
base_time = pd.to_datetime('9:00 AM')
df['cum_travel'] = df.groupby('id')['travel_delta'].cumsum()
df['start_time'] = (base_time + df['cum_travel']).dt.strftime('%I:%M %p').str.lstrip('0')
df['end_time'] = (pd.to_datetime(df['start_time']) + df['dur_delta']).dt.strftime('%I:%M %p').str.lstrip('0')

# 整理最终结果
df_final = df[['id', 'travel_time', 'dur', 'start_time', 'end_time']]
print(df_final)

运行上述代码后,df_final即为符合预期的结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:35:25