python - 使用python使用haversine公式对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)
我该如何解决这个问题?任何方向将不胜感激。
解决方案
这是一个大纲和一个工作代码示例 - 我在其中做出了一些关于保留/删除的假设。我假设数据框已排序。
- 首先计算到下一个点的距离,确实对纬度/经度对使用半正弦。这部分在我的实现中并不快——你可以找到更快。
- 使用
cumsum()
距离来创建距离组,其中组 1 是所有低于 50 的距离,组 2 是介于 50 和 100 之间的距离,等等... - 在每个组中,例如仅保留
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 以公里为单位返回距离 - 所以在这里我错误地做了一个 50 公里而不是米的例子。
gps_data["distance_group"] = gps_data.distance_cumsum // 50
filtered = gps_data.groupby(['distance_group']).first()
推荐阅读
- react-native - React 原生应用结构
- excel - 在字符“-”之前显示具有相同文本的其他单元格的内容
- reactjs - 如何避免反应中变量的内存共享?
- javascript - 如何触发 window.open 到特定的动态 URL?
- php - 从多级标记的 xml 中提取数据
- c++ - Windows 10 上的 Visual Studio 2012 C++ typedef 枚举信息消失
- drupal-7 - 最近博客的编辑块,Drupal 7
- angular - 在 HTML 元素事件处理程序中访问指令范围
- c# - Visual Studio 2017 中的 Newtonsoft Json.NET 性能问题
- python - 如何在循环中每 x 步创建一个新列表?