pandas按IMO分组计算船舶抵离港时间间隔的报错解决方案
问题解决:船舶在港停留时长计算
报错原因分析
- 你代码中的
if (df['State'] == "Sailing")逻辑错误:df['State'] == "Sailing"返回的是一整列布尔值(布尔Series),而if判断仅支持接收单个布尔值,系统无法判定一整列布尔值的整体真假,因此抛出ValueError: The truth value of a Series is ambiguous错误。 - 现有逻辑未按IMO号分组,会出现跨船舶计算时间间隔的问题,导致结果错误。
- 缺失Datetime列的类型转换步骤,字符串格式的时间无法直接做差值计算。
正确实现代码
import pandas as pd # 第一步:数据预处理,将时间列转为datetime类型 # 注意时间格式为日/月/年 时:分,显式指定format避免解析错误 data['Datetime'] = pd.to_datetime(data['Datetime'], format='%d/%m/%Y %H:%M') # 第二步:按IMO分组计算停留时长 def calc_dwell(group): # 分组内按时间排序,确保抵港记录在前、离港在后 group = group.sort_values('Datetime').reset_index(drop=True) # 计算当前行与上一行的时间差 group['timedelta'] = group['Datetime'] - group['Datetime'].shift(1) # 仅将离港行的时间差赋值给Time_int,转成HH:MM:SS格式,抵港行留空 group.loc[group['State'] == 'Sailing', 'Time_int'] = group['timedelta'].dt.floor('s').astype(str).str.split().str[-1] # 如果你需要的是小时数值(如18.13),可以替换成下面的代码 # group.loc[group['State'] == 'Sailing', 'Time_int'] = group['timedelta'].dt.total_seconds() / 3600 # 删掉临时计算列 group = group.drop(columns=['timedelta']) return group # 应用分组函数 data = data.groupby('IMO', group_keys=False).apply(calc_dwell) # 查看结果 print(data)
代码说明
- 按
IMO字段分组,确保仅在同一船舶的记录内计算时间间隔,不会跨船统计 - 分组内先按时间排序,避免记录顺序错乱导致的差值计算错误
- 仅对
State为Sailing的行赋值时间间隔,默认输出格式为HH:MM:SS,如果需要其他格式可以替换对应行的代码
内容的提问来源于stack exchange,提问作者Supriya Naik
相关产品推荐
相关产品推荐

