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

Pandas interpolate插值未返回预期结果求助

船舶AIS数据时间插值后参数未变化的问题解决

问题背景

原始CSV数据格式如下(BaseDateTime代表相邻条目间的时间差,单位:秒):

MMSI,BaseDateTime,LAT,LON,SOG,COG

11,0,27.29237,-90.96787,0.1,195.7
11,360,27.29237,-90.96793,0.1,188.0
111, 0,27.3538,-94.6253,0.1,35.3
111,180,27.35376,-94.62543,0.1,225.5

目标是将不均匀时间间隔转换为每30秒一条记录,但现有代码运行后,时间维度符合要求,但LAT、LON、SOG、COG字段未产生合理插值变化,输出示例:

MMSI,BaseDateTime,Latitude,Longitude,SOG,COG
11,0.0,27.29237,-90.96787,0.1,195.7
11,30.0,27.29237,-90.96787,0.1,195.7
...
11,360.0,27.29237,-90.96787,0.1,195.7

问题原因

核心错误在于时间索引的处理逻辑:
原代码直接将BaseDateTime(相邻时间差)转为timedelta作为索引,但resample需要基于连续的累计时间戳(即每个数据点对应的实际时间点),而非间隔值。比如MMSI=11的两条数据,实际时间点是0秒和360秒(0+360),但原代码把索引设为0秒和360秒的间隔值,导致resample时无法识别这两个点是时间轴上的起止点,插值只会沿用前值。

解决方案

修改代码,先为每个MMSI组计算累计时间戳,再基于累计时间轴进行resample和插值:

import pandas as pd
import numpy as np

def interpolater(df: np.ndarray):
    # 转换为DataFrame并修正字段类型
    df = pd.DataFrame(df, columns=['MMSI', 'BaseDateTime', 'LAT', 'LON', 'SOG', 'COG'])
    df['BaseDateTime'] = df['BaseDateTime'].astype(float)
    df[['LAT', 'LON', 'SOG', 'COG']] = df[['LAT', 'LON', 'SOG', 'COG']].astype(float)

    interpolated_dfs = []
    # 按MMSI分组处理单船数据
    for mmsi, group in df.groupby('MMSI'):
        # 关键修改:计算累计时间戳(将相邻时间差转为实际时间点)
        group['cum_time'] = group['BaseDateTime'].cumsum()
        # 用累计时间戳作为索引,转为timedelta格式
        group = group.set_index('cum_time')
        group.index = pd.to_timedelta(group.index, unit='s')
        
        # 按30秒间隔重采样,执行线性插值
        resampled = group.resample('30S').interpolate(method='linear')
        # 恢复MMSI字段(resample会丢失分组标识)
        resampled['MMSI'] = mmsi
        
        # 重置索引,将累计时间转为秒数作为新的BaseDateTime
        resampled = resampled.reset_index()
        resampled['BaseDateTime'] = resampled['cum_time'].dt.total_seconds()
        # 保留目标输出列
        resampled = resampled[['MMSI', 'BaseDateTime', 'LAT', 'LON', 'SOG', 'COG']]
        
        interpolated_dfs.append(resampled)

    # 合并所有分组结果并转为NumPy数组
    interpolated_df = pd.concat(interpolated_dfs)
    return interpolated_df.to_numpy()

验证效果

修改后,MMSI=11的330秒处的LON值会是线性插值结果:
-90.96787 + (-90.96793 - (-90.96787)) * (330 / 360) = -90.967925
其他字段也会按时间比例生成合理的插值结果,时间轴保持每30秒一条记录。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 07:57:53