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

Python中DataFrame乘客分段行程时长计算及性能优化求助

高效计算乘客行程时长的Pandas优化方案

嘿,我太懂你这种嵌套循环跑大数据集的痛苦了——每次看着进度条卡着不动真的让人崩溃。咱们直接用Pandas的分组聚合+向量化操作来重构代码,速度能提升好几个数量级!

先理清楚核心逻辑

你的需求是:对每个乘客(id)的每一段行程,用该行程的最晚leaving_time减去最早arriving_time;同一乘客同一天可能有多段行程(比如示例里的乘客b)。原来的循环问题在于反复切片原数据、重复转换时间格式,完全没用到Pandas的优化特性。


步骤1:一次性转换时间格式(只做一次!)

首先把日期和时间字段合并成完整的datetime对象,这样才能正确计算时间差——别像原来那样每次循环都转一次,太浪费资源了:

# 合并date和时间列,转换为datetime类型
my_df['arrive_full'] = pd.to_datetime(my_df['date'] + ' ' + my_df['arriving_time'])
my_df['leave_full'] = pd.to_datetime(my_df['date'] + ' ' + my_df['leaving_time'])

步骤2:分组聚合计算行程时长

用groupby按id和date分组(如果需要区分同一天内的多段行程,后面会说扩展方案),一次性计算每组的最早到达时间和最晚离开时间的差值:

# 分组计算每组的行程时长,然后重置索引方便合并
trip_duration = my_df.groupby(['id', 'date']).agg(
    travelTime=lambda group: group['leave_full'].max() - group['arrive_full'].min()
).reset_index()

或者写得更清晰易懂的版本,分开聚合再计算差值:

trip_duration = my_df.groupby(['id', 'date']).agg(
    earliest_arrive=('arrive_full', 'min'),
    latest_leave=('leave_full', 'max')
).assign(travelTime=lambda x: x['latest_leave'] - x['earliest_arrive']).drop(columns=['earliest_arrive', 'latest_leave']).reset_index()

步骤3:把结果合并回原DataFrame

最后用merge把计算好的travelTime关联到原数据的每一行:

my_df = my_df.merge(trip_duration, on=['id', 'date'], how='left')

为什么这个方案快这么多?

  • 避免了Python循环开销:groupby是Pandas底层用C实现的操作,比Python层面的嵌套循环快N倍
  • 只转换一次时间:原来的代码每次循环都要转时间,现在一次性完成
  • 批量处理聚合:一次遍历就完成所有分组的计算,不需要反复切片原数据

用你的示例数据跑出来的结果完全符合预期,比如乘客b2020/04/05的三段信号会被归为同一段行程,时长是08:57:14 - 08:52:02 = 00:05:12,每一行都会带上这个值。


扩展:如果需要区分同一天内的多段行程

如果你的“多段行程”是指同一天内乘客有中断的信号(比如中间有一段时间没检测到信号,之后又出现),那我们需要先给行程分段。可以通过判断当前行的到达时间是否晚于上一行的离开时间来划分行程组:

# 先按用户、日期、到达时间排序,保证时间顺序正确
my_df = my_df.sort_values(['id', 'date', 'arrive_full'])

# 标记行程段:同一用户日期下,当前到达时间晚于上一次离开时间,就标记为新行程
my_df['trip_segment'] = (
    my_df.groupby(['id', 'date'])['arrive_full']
    .shift() < my_df.groupby(['id', 'date'])['leave_full'].shift()
).fillna(False).cumsum()

# 现在按id、date、trip_segment分组计算时长
trip_duration = my_df.groupby(['id', 'date', 'trip_segment']).agg(
    earliest_arrive=('arrive_full', 'min'),
    latest_leave=('leave_full', 'max')
).assign(travelTime=lambda x: x['latest_leave'] - x['earliest_arrive']).reset_index()

# 合并回原数据
my_df = my_df.merge(trip_duration, on=['id', 'date', 'trip_segment'], how='left')

这个版本就能准确区分同一天内的多个不连续行程了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 23:52:41