提问者:小点点

使用Python使用哈弗正弦公式对GPS数据进行下采样


我有一个高频率的gps数据,我想每50米采样一次,即每50米保留gps纬度和经度,并在点之间丢弃。我在网上找到了一个python代码,基本上计算两点之间的距离。但我不知道如何基本上从csv中读取lat和long值并将其输入函数并计算距离。如果距离达到50米,我只是保存gps坐标。到目前为止,我有以下python代码

from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])

    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    r = 6371 # Radius of earth in kilometers. Use 3956 for miles
    return c * r

x1 = 52.19421607 
x2 = 52.20000327 
y1 = -1.484984011 
y2 = -1.48533465
result = haversine(x1,y1,x2,y2)    #need to give input from a csv
#if result is greater than 50m , save the coordinates
print(result)   

我该如何解决这个问题?任何方向都可以。


共1个答案

匿名用户

这里有一个大纲和一个工作代码示例——我在这里做了一些关于保留/删除的假设。我假设数据帧已经排序。

    < li >首先计算到下一个点的距离,实际上,对于纬度/经度对使用哈弗辛。在我的实现中,这部分并不快——你可以找到更快的。 < li >使用距离的< code>cumsum()来创建距离组,其中组1是所有小于50的距离,组2是介于50和100之间的距离,依此类推... < li >例如,在每个组中,只保留< code>first()

请注意,这是基于组的大约每50个单位,因此请注意这不同于从一个点跳到下一个最接近50个单位的点并重复。但是为了减少数据,这应该没问题。

在伦敦周围生成一些随机数据。

import numpy as np
import sklearn
import pandas as pd

LONDON =  (51.509865, -0.118092)

random_gps = np.random.random( (10000,2) ) / 25
random_gps[:,0] += np.arange(random_gps.shape[0]) / 25

random_gps[:,0] += LONDON[0]
random_gps[:,1] += LONDON[1]

gps_data = pd.DataFrame( random_gps, columns=["lat","long"] )

移动数据以获取下一个点的经度/经度

gps_data['next_lat'] = gps_data.lat.shift(1)
gps_data['next_long'] = gps_data.long.shift(1)

gps_data.head()

定义距离度量。这部分可以通过使用带有numpy的矢量表达式来提高速度,因此如果速度很重要,请更改这部分。

from sklearn.neighbors import DistanceMetric

dist = DistanceMetric.get_metric('haversine')

EARTH_RADIUS = 6371.009

def haversine_distance(row):
    point_a = np.array([[row.lat, row.long]])
    point_b = np.array([[row.next_lat, row.next_long]])
    return EARTH_RADIUS * dist.pairwise(np.radians(point_a), np.radians(point_b) )[0][0]
    

并应用我们的距离函数(慢速部分,可以改进)

gps_data["distance_to_next"] = gps_data.apply( haversine_distance, axis=1)
gps_data["distance_cumsum"] = gps_data.distance_to_next.cumsum()

最后,创建组并删除。(!)haversine 以 KM 为单位返回距离 - 所以在这里我错误地做了一个 50 公里而不是米的例子。

gps_data["distance_group"] = gps_data.distance_cumsum // 50

filtered = gps_data.groupby(['distance_group']).first()