如何对含MMSI、datetime的多列船舶CSV数据进行分钟级插值?
船舶时序数据规整:分钟级插值实现方案
完全可以通过插值实现分钟级的规整数据,Pandas的插值功能并没有过时——大概率是你用了旧版本API或者不当的实现方式。下面是针对你的船舶数据的具体处理步骤:
核心实现步骤
1. 数据读取与预处理
先读取CSV并解析时间字段,按船舶唯一标识MMSI分组,确保单船数据单独处理:
import pandas as pd # 读取数据,自动解析时间列 df = pd.read_csv('ship_data.csv', parse_dates=['BaseDateTime']) # 按MMSI分组,避免不同船舶的数据混在一起处理 ship_groups = df.groupby('MMSI')
2. 生成分钟级时间序列并插值
对每个船舶分组,生成覆盖原数据时间范围的分钟级时间戳,再通过插值填充空值:
def process_ship_data(group): # 将时间列设为索引 group = group.set_index('BaseDateTime') # 生成从数据最早到最晚时间的分钟级时间序列 minutely_timestamps = pd.date_range(start=group.index.min(), end=group.index.max(), freq='T') # 重新索引到分钟级,空值留待插值 resampled_group = group.reindex(minutely_timestamps) # 填充MMSI(同组船舶MMSI一致,用前向填充即可) resampled_group['MMSI'] = resampled_group['MMSI'].ffill() # 对经纬度、航速、航向进行时间加权插值 # method='time'会根据时间间隔自动加权,比普通线性插值更贴合时序数据特性 resampled_group[['LAT', 'LON', 'SOG', 'COG']] = resampled_group[['LAT', 'LON', 'SOG', 'COG']].interpolate(method='time') return resampled_group # 应用到所有船舶分组,合并结果并重置索引 final_result = ship_groups.apply(process_ship_data).reset_index(level=0, drop=True).reset_index() # 把索引列改回原时间字段名 final_result = final_result.rename(columns={'index': 'BaseDateTime'})
3. 插值方法的优化建议
- 对于
COG(航向)这种环形数据(0°-360°),直接线性插值可能出现从350°跳到10°的不合理情况,可以自定义环形插值逻辑:先将角度转为笛卡尔坐标(sin、cos值),插值后再转回角度。 - 如果
SOG(航速)存在大量0值(船舶停航),可以结合ffill()填充连续停航时段,再对航速变化时段用插值处理,避免数值异常波动。
关于“Pandas插值过时”的说明
你觉得方法过时,可能是混淆了旧版本的参数(比如早期版本的time插值需要额外配置),但在Pandas 1.x及2.x版本中,interpolate(method='time')依然是处理时序数据插值的标准方法,完全可以正常使用。
内容的提问来源于stack exchange,提问作者Andreas Ravnholt
相关产品推荐
相关产品推荐

