首页 GIS基础理论 出租车轨迹数据怎么洗?噪点如何去除?

出租车轨迹数据怎么洗?噪点如何去除?

作者: GIS研习社 更新时间:2025-12-17 10:00:56 分类:GIS基础理论

你的轨迹数据“发疯”了吗?先别急着骂算法

上周一位在交通局实习的研究生给我发消息:‘老师,我导入的出租车轨迹点,有的飞到天上,有的钻进地下车库,还有的在江面上画龙舟……这数据还能用吗?’——这几乎是每个处理轨迹数据的新手必经的‘崩溃时刻’。别慌,今天我就手把手带你把‘发疯’的数据‘洗’回正常人。”

出租车轨迹数据怎么洗?噪点如何去除?

轨迹噪点从哪来?GPS不是万能的

你以为出租车顶上那个小蘑菇头(GPS天线)是千里眼?错。它其实是个‘路痴+近视眼’:

  • 高楼峡谷效应:城市CBD里,卫星信号被玻璃幕墙反复反射,定位点可能偏移几百米——就像你在KTV包厢里听隔壁唱歌,以为声音来自正前方。
  • 隧道/地下车库:信号直接归零,设备要么记录最后已知位置(导致车辆原地打转),要么胡乱插值(突然瞬移到三公里外)。
  • 设备故障或人为干扰:司机拔掉GPS、计价器死机、甚至故意绕路刷单,都会产生‘幽灵轨迹’。
我在参与某市智慧交通项目时,曾发现一辆车凌晨3点在长江大桥上来回折返17次——调取监控才发现是司机在桥下睡觉,GPS因金属桥体反射产生‘鬼影漂移’。

三步清洗法:像筛米一样筛掉脏数据

清洗轨迹不是玄学,核心就三步:去异常 → 补缺失 → 平滑抖动。下面用Python + GeoPandas实战演示(代码可直接复制运行)。

第一步:暴力删除离群点(空间+速度双过滤)

先定义常识:出租车不可能每秒跑200米(约720km/h),也不可能停在西湖中央。用这两个硬指标砍掉最离谱的点:

import geopandas as gpd
from shapely.geometry import Point

# 假设df是包含geometry列的GeoDataFrame
df['speed'] = df.groupby('taxi_id')['geometry'].apply(
    lambda x: x.distance(x.shift(1)) / (x.index.to_series().diff().dt.total_seconds() / 3600)
)

# 删除速度>120km/h 或位于水体中的点(需提前准备水体shp文件)
valid_speed = df[df['speed'] <= 120]
water_bodies = gpd.read_file('water.shp')
cleaned = valid_speed[~valid_speed.within(water_bodies.unary_union)]

第二步:智能插值补洞(别让车“瞬移”)

遇到GPS信号丢失的空白段,千万别用直线连接!要用时空约束插值——想象成给断掉的珍珠项链补珠子,既要对齐孔位(空间连续),又要符合穿线节奏(时间均匀):

from scipy.interpolate import interp1d
import numpy as np

# 按车辆分组插值
def interpolate_trajectory(group):
    t = group.index.values.astype(np.int64) // 10**9  # 转为Unix时间戳
    x = group.geometry.x.values
    y = group.geometry.y.values
    
    # 线性插值函数
    fx = interp1d(t, x, kind='linear', fill_value='extrapolate')
    fy = interp1d(t, y, kind='linear', fill_value='extrapolate')
    
    # 生成每10秒一个点的时间序列
    new_t = np.arange(t.min(), t.max(), 10)
    new_points = [Point(fx(t_val), fy(t_val)) for t_val in new_t]
    return gpd.GeoSeries(new_points, index=new_t)

# 应用插值
df_interpolated = df.groupby('taxi_id').apply(interpolate_trajectory).explode()

第三步:卡尔曼滤波平滑(消除“帕金森式抖动”)

即使删了离群点,轨迹仍会像帕金森患者的手一样抖动。这时请出卡尔曼滤波器——它像给数据戴了降噪耳机,只保留符合物理规律的运动趋势:

from pykalman import KalmanFilter

# 对单辆车轨迹应用卡尔曼滤波
coords = np.column_stack([df.geometry.x, df.geometry.y])
kf = KalmanFilter(transition_matrices=[[1,1,0,0],[0,1,0,0],[0,0,1,1],[0,0,0,1]],
                   observation_matrices=[[1,0,0,0],[0,0,1,0]])
smoothed_coords, _ = kf.filter(coords)

# 重建平滑后的轨迹
df_smoothed = gpd.GeoDataFrame(
    geometry=[Point(xy) for xy in smoothed_coords], 
    crs=df.crs
)

终极心法:没有完美的清洗,只有合理的妥协

记住:清洗数据不是追求100%干净,而是在精度和完整性之间找平衡点。我见过团队为了删掉0.1%的噪点,误伤了30%的有效数据——这比留着噪点更灾难。

实战建议:先用宽松阈值快速清洗80%明显错误,再对剩余20%可疑数据人工抽检。毕竟,算法是死的,人是活的。

现在轮到你了!你在清洗轨迹数据时踩过什么坑?是遇到过“穿越大楼”的幽灵车,还是被司机绕路刷单坑过?评论区说出你的血泪史,点赞最高的三位送《轨迹数据处理避坑指南》电子书!

相关文章