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

基于点间距高效精简GPS轨迹点数量的技术方案求助

高效精简GPS轨迹DataFrame方法

问题背景

现有包含车辆GPS坐标的DataFrame,字段为Timestamp、Latitude、Longitude。采样间隔在1秒到30秒之间,由GPS接收器逻辑(含速度因素)决定,间隔不稳定。低速行驶或静止时轨迹会包含数千个GPS点,数据量冗余,需要精简:仅保留与上一个保留点间距至少50米的点,两点间距离采用Haversine公式计算。

数据示例

TimestampLatitudeLongitude
0 days 00:00:0051.15139.61053
0 days 00:00:2851.15139.61049
0 days 00:00:2951.15139.61048
0 days 00:00:3151.15139.61048
0 days 00:00:3351.15139.61048

Haversine距离计算实现

标量版本

from math import radians, cos, sin, asin, sqrt
def haversine(lat1, lon1, lat2, lon2):
    """
    计算地球上两点间的大圆距离(单位:米)
    参数为十进制度数格式的经纬度
    """
    # 转换为弧度
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    # Haversine公式
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    # 地球半径取6371000米
    return 6371000 * c

向量化版本

适用于批量计算相邻点的距离:

import numpy as np
def haversine_vec(df):   
    data = np.deg2rad(df[['Latitude', 'Longitude']])                     
    diff = data.shift() - data
    d = np.sin(diff['Latitude']/2)**2 + np.cos(data['Latitude'])*np.cos(data['Latitude'].shift()) * np.sin(diff['Longitude']/2)**2
    return 2 * 6371000 * np.arcsin(np.sqrt(d))

现有低效方法

当前采用纯Python遍历标记的方式,效率极低,不适用于大型数据集:

import numpy as np
def reduce_gps(df): 
    mask = np.full(len(df), False)
    cpos = 0
    lat_col = df.columns.get_loc('Latitude')
    lon_col = df.columns.get_loc('Longitude')
    for pos in range(len(mask)):
        if haversine(df.iloc[cpos, lat_col], df.iloc[cpos, lon_col], 
                     df.iloc[pos, lat_col], df.iloc[pos, lon_col]) > 50 or (pos==len(mask)-1):
            cpos = pos
            mask[pos] = True
    return df[mask]

高效解决方案

使用Numba的JIT编译加速循环逻辑,将Python循环转换为机器码,处理大型数据集速度提升显著:

import numpy as np
import pandas as pd
from math import radians, cos, sin, asin, sqrt
from numba import jit

@jit(nopython=True)
def haversine_numba(lat1, lon1, lat2, lon2):
    """Numba加速的Haversine距离计算"""
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    dlon = lon2 - lon1
    dlat = lat2 - lat1
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a))
    return 6371000 * c

@jit(nopython=True)
def reduce_gps_numba(lats, lons, threshold=50):
    """Numba加速的轨迹精简逻辑"""
    n = len(lats)
    mask = np.zeros(n, dtype=np.bool_)
    mask[0] = True  # 保留第一个点
    last_keep_idx = 0
    for i in range(1, n):
        dist = haversine_numba(lats[last_keep_idx], lons[last_keep_idx], lats[i], lons[i])
        # 满足距离阈值或最后一个点时标记保留
        if dist > threshold or i == n-1:
            mask[i] = True
            last_keep_idx = i
    return mask

def reduce_gps(df, threshold=50):
    """对外调用的精简函数"""
    lats = df['Latitude'].values
    lons = df['Longitude'].values
    mask = reduce_gps_numba(lats, lons, threshold)
    return df[mask]

使用方式

读取样本数据后,直接调用函数即可:

df = pd.read_csv('样本数据路径')
reduced_df = reduce_gps(df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:52:06