出租车轨迹数据怎么洗?噪点如何去除?
“出租车轨迹数据怎么洗?噪点如何去除?”是很多 GIS 初学者、交通数据分析人员和 WebGIS 开发者都会遇到的问题。出租车 GPS 轨迹看起来只是经纬度和时间戳,但真实数据里经常混有漂移点、重复点、时间乱序、速度异常、跨城市跳点等问题。如果不先做轨迹数据清洗,后续的路径重建、OD 分析、热力图、道路匹配和出行特征统计都会被明显带偏。

引言:出租车轨迹数据清洗到底要解决什么问题
出租车轨迹数据清洗的核心目标,不是把轨迹“修得好看”,而是尽量保留真实行驶过程,去除明显不符合车辆运动规律和数据采集逻辑的记录。
一条常见的出租车 GPS 记录通常包含以下字段:
- 车辆 ID:用于区分不同出租车。
- 经度、纬度:车辆定位点坐标。
- 时间戳:GPS 上报时间。
- 速度、方向角:部分数据会提供,也可能缺失。
- 载客状态:空车、载客、停运等状态,常用于 OD 提取。
实际分析中,出租车轨迹噪点去除通常要处理四类问题:记录层面的错误、时间层面的错误、空间层面的错误、运动规律层面的异常。本文用 GIS 分析视角,给出一套可复用的清洗流程,适合在 Python、PostGIS、QGIS 或 ArcGIS Pro 前处理阶段使用。
背景:为什么出租车 GPS 轨迹会有噪点
出租车轨迹噪点并不一定是数据供应商“质量差”,更多时候来自 GPS 定位机制和车载终端上报机制。
1. 城市峡谷导致定位漂移
高楼密集区、隧道口、立交桥下方、地下停车场附近,经常会出现 GPS 信号反射或遮挡。结果是车辆明明在道路上行驶,定位点却漂到河里、楼里、隔壁道路甚至几百米之外。
2. 上报间隔不稳定
有的车辆每 10 秒上报一次,有的车辆可能 30 秒或 1 分钟才上报一次。网络延迟、设备休眠、信号丢失还会导致时间间隔忽长忽短。时间间隔不稳定会影响速度计算和轨迹插值。
3. 设备重复上传或补传
出租车终端可能会重复上传同一时刻的记录,也可能在网络恢复后集中补传历史记录。如果不按车辆 ID 和时间戳排序,就会看到轨迹线来回穿插。
4. 坐标系或经纬度字段错误
有些数据使用 WGS84,有些经过 GCJ-02 偏移,也有数据在导出时把经纬度字段写反。坐标系问题会造成整体偏移,经纬度反置则会让点直接落到错误区域。
判断出租车轨迹数据是否需要清洗,不要只看表格字段是否完整,一定要把点加载到地图上,并按车辆和时间连线检查。
原理:出租车轨迹噪点去除的判断逻辑
出租车轨迹数据清洗一般遵循“先简单规则,后复杂模型”的原则。不要一开始就做道路匹配或机器学习异常检测,否则很容易把基础数据错误掩盖掉。
1. 唯一性规则
同一辆车、同一时间戳、同一坐标的记录通常只需要保留一条。重复点会放大停留时间、影响轨迹点密度统计,也会干扰后续速度计算。
2. 时间连续性规则
同一辆车的轨迹必须按时间升序排列。如果时间倒序或乱序,计算出来的速度、距离、行驶方向都不可靠。
3. 空间范围规则
出租车轨迹点应位于研究区范围或合理缓冲区内。例如研究对象是北京市出租车,就可以用北京市行政边界外扩一定距离作为空间过滤范围。
4. 速度阈值规则
出租车在城市道路中的速度有合理上限。若相邻两个 GPS 点之间的距离除以时间间隔得到极高速度,通常说明其中至少一个点是漂移点。
5. 加速度和转向规则
如果车辆在极短时间内出现不合理加速、急停、反向跳变,也可能是轨迹噪点。但这类规则要谨慎使用,因为真实交通中确实存在急刹车、掉头、拥堵等情况。
步骤:出租车轨迹数据怎么洗
下面给出一套适合大多数出租车轨迹数据清洗的操作流程。无论你使用 Python、PostGIS、QGIS 还是 ArcGIS Pro,都可以按照这个顺序处理。
步骤 1:统一字段和数据类型
先把字段整理成稳定结构,至少包括车辆 ID、时间戳、经度、纬度。如果速度、方向角和载客状态可用,也建议保留。
| 字段 | 建议名称 | 说明 |
|---|---|---|
| 车辆编号 | taxi_id | 用于分组处理每辆车的轨迹 |
| 时间 | timestamp | 转换为标准日期时间类型 |
| 经度 | lon | 通常为 WGS84 或 GCJ-02 经度 |
| 纬度 | lat | 通常为 WGS84 或 GCJ-02 纬度 |
| 载客状态 | status | 可用于 OD 提取和行程切分 |
如果时间字段仍是字符串,必须先转换为日期时间类型。经纬度字段也要转换为数值型,避免出现空格、中文符号或异常字符。
步骤 2:删除空值和明显非法坐标
先删除 taxi_id、timestamp、lon、lat 中为空的记录。然后检查经纬度范围。
- 经度通常应在 -180 到 180 之间。
- 纬度通常应在 -90 到 90 之间。
- 中国城市出租车数据一般不会出现负经度。
- 如果 lon 小于 lat,且数据落点明显异常,要检查是否经纬度写反。
这一步属于基础轨迹数据清洗,能快速去掉一批明显无效点。
步骤 3:按车辆 ID 和时间排序
出租车轨迹噪点去除必须按单车轨迹进行,不能把所有车辆混在一起计算距离和速度。正确顺序是先按 taxi_id 分组,再按 timestamp 排序。
import pandas as pd
df = pd.read_csv("taxi_gps.csv")
df["timestamp"] = pd.to_datetime(df["timestamp"], errors="coerce")
df["lon"] = pd.to_numeric(df["lon"], errors="coerce")
df["lat"] = pd.to_numeric(df["lat"], errors="coerce")
df = df.dropna(subset=["taxi_id", "timestamp", "lon", "lat"])
df = df.sort_values(["taxi_id", "timestamp"])
如果这一步不做,后面的速度异常检测基本没有意义。
步骤 4:删除重复记录
重复记录可以按业务目标分两种情况处理。如果同一辆车、同一时间戳、同一坐标完全一致,一般直接删除。如果同一辆车、同一时间戳出现多个不同坐标,则需要进一步判断。
df = df.drop_duplicates(subset=["taxi_id", "timestamp", "lon", "lat"])
对于同一 taxi_id 和 timestamp 对应多个坐标的情况,建议先标记出来,不要立即随机保留一条。可以结合速度、空间范围和前后点连续性决定保留哪一个。
步骤 5:做研究区空间范围过滤
如果你的研究区是某个城市,建议准备行政边界面数据,外扩 1 到 5 公里作为容差范围,再用空间连接或点面包含关系过滤。这样可以去除落在海上、外省、远离城市区域的异常点。
在 QGIS 中可以这样做:
- 加载出租车点数据和城市边界面数据。
- 确认两者坐标系一致。
- 对城市边界执行缓冲区工具,例如外扩 3000 米。
- 使用“按位置提取”工具,保留落在缓冲区内的轨迹点。
- 导出为新的 GeoPackage 或 CSV 文件。
在 PostGIS 中,可使用 ST_Within 或 ST_Intersects 配合城市边界过滤:
SELECT t.*
FROM taxi_points t
JOIN city_boundary b
ON ST_Intersects(t.geom, ST_Buffer(b.geom, 3000));
注意:如果 geom 使用经纬度坐标系,直接缓冲 3000 并不代表 3000 米。应先转换到适合本地的投影坐标系,或者使用 geography 类型处理距离。
步骤 6:计算相邻点距离、时间差和速度
速度异常检测是出租车轨迹噪点去除最常用的方法。基本思路是:对同一辆车的相邻两点计算距离和时间差,再得到平均速度。
import geopandas as gpd
from shapely.geometry import Point
gdf = gpd.GeoDataFrame(
df,
geometry=gpd.points_from_xy(df["lon"], df["lat"]),
crs="EPSG:4326"
)
# 示例:如果研究区适合使用 Web Mercator,可临时投影到米单位坐标系
# 更严谨做法是选择本地投影坐标系
gdf_m = gdf.to_crs("EPSG:3857")
gdf_m["prev_geom"] = gdf_m.groupby("taxi_id")["geometry"].shift(1)
gdf_m["prev_time"] = gdf_m.groupby("taxi_id")["timestamp"].shift(1)
gdf_m["dt_sec"] = (gdf_m["timestamp"] - gdf_m["prev_time"]).dt.total_seconds()
gdf_m["dist_m"] = gdf_m.apply(
lambda row: row["geometry"].distance(row["prev_geom"]) if row["prev_geom"] else None,
axis=1
)
gdf_m["speed_kmh"] = gdf_m["dist_m"] / gdf_m["dt_sec"] * 3.6
计算速度时要特别注意投影坐标系。不要直接用经纬度坐标计算欧氏距离,否则距离单位是“度”,不是米。
步骤 7:根据速度阈值标记噪点
城市出租车轨迹中,如果相邻点推算速度远高于城市道路可能速度,通常可以标记为异常。阈值应结合城市道路条件、采样间隔和业务目的设定。
- 普通城市道路分析:可先检查大于 120 km/h 的点段。
- 包含高速路场景:阈值可适当放宽。
- 采样间隔很长的数据:速度阈值不能过于严格。
- 用于精细道路匹配:应更谨慎,避免删除真实快速路轨迹。
speed_threshold = 120
gdf_m["is_speed_noise"] = (
(gdf_m["dt_sec"] > 0) &
(gdf_m["speed_kmh"] > speed_threshold)
)
clean_gdf = gdf_m[~gdf_m["is_speed_noise"]].copy()
更稳妥的做法不是只删除当前点,而是同时检查前一个点和后一个点。如果某个点与前后点都形成异常跳变,而前后点之间相对连续,那么这个中间点很可能是漂移点。
步骤 8:处理时间间隔异常
如果相邻点时间差为 0 或负数,说明有重复时间或时间乱序,应删除或单独检查。如果时间差过大,例如超过 30 分钟,通常不应把两个点直接连成一条连续轨迹。
可以用时间间隔进行行程切分:
max_gap_sec = 30 * 60
gdf_m["new_segment"] = (
(gdf_m["dt_sec"].isna()) |
(gdf_m["dt_sec"] <= 0) |
(gdf_m["dt_sec"] > max_gap_sec)
)
gdf_m["segment_id"] = gdf_m.groupby("taxi_id")["new_segment"].cumsum()
这样处理后,轨迹线生成、道路匹配和停留点识别会更合理。
步骤 9:结合道路数据做进一步检查
如果你有道路中心线数据,可以检查出租车点到最近道路的距离。距离道路过远的点可能是 GPS 漂移点,但不能简单一刀切删除。
- 高架桥、辅路、隧道附近容易出现道路数据不完整问题。
- 新建道路可能不在旧版路网中。
- 停车场、加油站、出租车场站不一定在道路中心线上。
- 坐标系不一致会导致所有点到道路距离都异常。
道路距离过滤更适合作为“疑似噪点标记”,而不是唯一删除条件。
步骤 10:导出清洗结果并保留质量字段
完成出租车轨迹数据清洗后,不建议只导出一个“干净数据”。更好的做法是保留质量控制字段,方便追溯。
- is_duplicate:是否重复记录。
- is_outside_area:是否超出研究区。
- speed_kmh:相邻点推算速度。
- is_speed_noise:是否速度异常。
- segment_id:轨迹分段编号。
- clean_status:保留、删除、待人工检查。
这些字段对后续复核、论文方法说明、项目交付都很有用。
常见坑:出租车轨迹噪点去除时最容易犯的错误
1. 直接用经纬度计算距离
经纬度坐标的单位是度,不是米。出租车轨迹数据清洗中如果要计算距离、速度、缓冲区,应转换到合适的投影坐标系,或使用支持椭球距离计算的方法。
2. 把所有超速点直接删除
速度异常只能说明相邻点段异常,不一定说明当前点一定是噪点。特别是一个点前后都异常时,需要判断是当前点漂移,还是前一个点或后一个点异常。
3. 忽略采样间隔
10 秒采样和 5 分钟采样的轨迹,清洗策略不能完全一样。采样间隔越长,轨迹越稀疏,短距离绕行、快速路通行、隧道补点都会使速度判断变得不稳定。
4. 没有区分停留点和重复点
同一辆车在同一地点停留很久,不等于重复点。真正的重复点通常是同一时间戳、同一坐标重复出现。停留点在出租车候客、等红灯、拥堵分析中可能很有价值。
5. 先做道路匹配再清洗
道路匹配可以修正轨迹,但不能替代基础清洗。大量漂移点、乱序点和重复点会让道路匹配结果出现跳路、绕路、错误吸附等问题。
6. 坐标系混用
如果出租车点是 GCJ-02,而道路数据是 WGS84 或投影坐标,二者会产生系统偏移。做道路距离检查或道路匹配前,必须确认坐标体系一致。
方法比较:不同出租车轨迹数据清洗方法怎么选
| 方法 | 适用场景 | 优点 | 局限 |
|---|---|---|---|
| 字段规则清洗 | 空值、非法经纬度、重复记录 | 简单、稳定、适合第一步处理 | 不能识别复杂漂移点 |
| 空间范围过滤 | 研究区外异常点 | 直观,适合城市级数据 | 边界外真实运营点可能被误删 |
| 速度阈值过滤 | 跳点、漂移点、定位异常 | 通用性强,易解释 | 阈值需要结合采样间隔和道路条件 |
| 加速度与方向变化检测 | 精细轨迹质量控制 | 能识别不连续运动 | 对低频数据不稳定 |
| 道路距离过滤 | 有可靠路网数据的城市交通分析 | 接近真实道路约束 | 依赖路网质量和坐标一致性 |
| 地图匹配 | 路径还原、路段流量分析 | 可得到道路级轨迹 | 不适合作为原始数据第一步清洗 |
实际项目中,推荐组合使用:字段规则清洗、时间排序、空间范围过滤、速度异常检测、轨迹分段、道路距离复核。这样既能覆盖大部分出租车轨迹噪点,又不会过度删除有效数据。
检查清单:清洗后如何验证出租车轨迹数据是否可靠
完成出租车轨迹数据清洗后,建议按下面清单复查,不要只看删除了多少记录。
- 是否每辆车的轨迹都按时间升序排列?
- 是否删除了 taxi_id、timestamp、lon、lat 为空的记录?
- 经纬度是否落在合理范围内?
- 是否检查过经纬度字段是否写反?
- 是否统一了坐标系和坐标偏移类型?
- 是否按车辆 ID 分组计算速度,而不是全表直接计算?
- 速度计算是否使用米单位距离?
- 是否保留了异常标记字段,方便后续追溯?
- 是否抽样在 QGIS 或 ArcGIS Pro 中连线查看轨迹形态?
- 是否对删除前后点数、车辆数、时间范围做了统计对比?
如果清洗后车辆数大幅减少、某些时间段完全消失、轨迹集中断裂,说明规则可能过严,需要回看阈值设置。
FAQ:出租车轨迹数据清洗常见问题
出租车轨迹数据清洗一定要做道路匹配吗?
不一定。道路匹配适合需要还原行驶路段、统计道路流量或计算路径的场景。如果只是做点密度、热力图、OD 分析,基础轨迹数据清洗和合理的轨迹分段通常已经足够。
出租车轨迹噪点去除的速度阈值应该设多少?
没有固定答案。城市道路分析可以先从 100 到 120 km/h 作为检查阈值,高速路较多的城市可适当提高。更好的方式是先统计速度分布,查看极端值,再结合城市道路条件设置阈值。
时间间隔很大的两个点要不要删除?
通常不需要直接删除,但不应把它们当作连续轨迹连接。建议用时间间隔生成新的 segment_id,把长时间中断前后的轨迹分成不同片段。
停在原地的点算噪点吗?
不一定。出租车可能在等客、等红灯、拥堵或停车场停留。只有同一时间戳、同一坐标重复出现,或者数据明显由设备重复上传造成,才应作为重复记录处理。
QGIS 可以完成出租车轨迹数据清洗吗?
可以完成一部分,例如加载点数据、检查空间分布、删除非法点、按位置提取、生成轨迹线、可视化抽查。但如果数据量很大,建议使用 Python、PostGIS 或数据库流程批量处理。
为什么清洗后轨迹还是会穿过建筑物或河流?
基础清洗只能去除明显异常点,不能保证轨迹线完全沿道路行驶。GPS 点之间的连线是直线连接,不等于真实行驶路线。如果需要道路级路径,需要进一步做地图匹配。
出租车轨迹数据清洗后应该保存成什么格式?
小规模数据可以保存为 GeoPackage、GeoJSON 或 CSV。大规模城市出租车轨迹建议存入 PostGIS,便于建立空间索引、按时间和车辆查询,并支持后续空间分析。
结论:先保证轨迹可信,再做空间分析
出租车轨迹数据怎么洗,关键在于按顺序处理:统一字段、删除空值和非法坐标、按车辆和时间排序、去重、空间范围过滤、计算速度、标记异常点、分段保存。出租车轨迹噪点去除不能只依赖一个阈值,而应结合时间、空间、速度、道路约束和业务场景综合判断。
对 GIS 读者来说,最重要的习惯是:每一步清洗都保留标记字段,每一类规则都抽样上图检查。只有确认轨迹数据本身可靠,后续的 OD 分析、出行热力图、路径重建和交通运行评价才有可信基础。