如何按delta_t条件拆分Pandas DataFrame中的行程数据
解决行程拆分问题:基于delta_t拆分Pandas行程数据
这问题我之前处理过类似的,核心是通过标记拆分点再生成新的行程ID,一步步来很清晰:
步骤1:构造示例数据(方便验证)
先把你提供的示例数据转换成可运行的DataFrame:
import pandas as pd import numpy as np data = { 'TripID': [1,1,1,1,1,1,2,2,2], 'Lat': [53.55,53.58,53.60,53.60,53.58,53.59,52.01,52.34,52.33], 'Lon': [9.99,9.99,9.98,9.98,9.99,9.97,10.04,10.05,10.07], 'time': [74,75,76,81,82,83,64,65,66], 'delta_t': [1,1,5,1,1,np.nan,1,1,np.nan] } df = pd.DataFrame(data)
步骤2:标记拆分起始点
我们需要找到每个原行程中,delta_t > 1的记录——它的下一条记录就是新行程的起点。通过groupby和shift来标记这些起点:
# 标记delta_t>1的位置,然后向下移位,得到新行程的起始行 df['split_start'] = df.groupby('TripID')['delta_t'].apply(lambda x: x > 1).shift(1).fillna(False) # 在每个原TripID组内,累计拆分标记,得到子行程的编号 df['sub_trip'] = df.groupby('TripID')['split_start'].cumsum()
步骤3:生成新的TripID
把原TripID和子行程编号组合,生成唯一的新行程ID。你可以选择字符串格式(可读性强)或者连续整数格式(方便后续操作):
# 方案1:字符串格式(如"1_0"、"1_1") df['new_TripID'] = df['TripID'].astype(str) + '_' + df['sub_trip'].astype(str) # 方案2:连续整数格式(从1开始递增) # df['new_TripID'] = df.groupby(['TripID', 'sub_trip']).ngroup() + 1
步骤4:处理delta_t的NaN值
用你提供的代码逻辑,给每个新行程的最后一条记录设置delta_t为NaN:
# 若用方案2的整数ID,直接用你提供的代码即可;若用字符串ID,调整判断逻辑如下 df.loc[df['new_TripID'].diff().shift(-1) != 0, 'delta_t'] = np.nan
步骤5:清理中间列(可选)
删除不需要的中间辅助列,并重命名新ID列为原TripID:
df = df.drop(['split_start', 'sub_trip', 'TripID'], axis=1).rename(columns={'new_TripID': 'TripID'})
最终结果
运行后你会得到拆分后的DataFrame:
Lat Lon time delta_t TripID 0 53.55 9.99 74 1.0 1_0 1 53.58 9.99 75 1.0 1_0 2 53.60 9.98 76 NaN 1_0 3 53.60 9.98 81 1.0 1_1 4 53.58 9.99 82 1.0 1_1 5 53.59 9.97 83 NaN 1_1 6 52.01 10.04 64 1.0 2_0 7 52.34 10.05 65 NaN 2_0 8 52.33 10.07 66 NaN 2_0
关键逻辑说明
- 我们通过
groupby保证只在同一个原行程内判断拆分条件,不会跨行程误判; cumsum累计拆分标记,让每个拆分后的子行程获得唯一的组内编号;- 最后处理NaN时,通过判断
new_TripID的变化,精准定位每个新行程的最后一条记录。
内容的提问来源于stack exchange,提问作者Jan Kaiser
相关产品推荐
相关产品推荐

