python - 计算时间顺序坐标之间的距离和速度

标签 python gps distance haversine

我有一个 csv 包含给定用户的位置(纬度经度),由 id 字段表示,在给定时间( 时间戳)。我需要为每个用户计算一个点和连续点之间的距离和速度。例如,对于 ID 1,我需要找到点 1 和点 2、点 2 和点 3、点 3 和点 4 之间的距离和速度,等等。鉴于我正在使用地球上的坐标,我知道 Haversine 度量将用于距离计算,但是,我不确定如何在我的问题的时间和用户顺序方面迭代我的文件。鉴于此,使用 python,我如何遍历我的文件以按用户和时间对事件进行排序,然后计算每个事件之间的距离和速度?

理想情况下,输出将是第二个 csv,类似于:ID#, start_time, start_location, end_time, end_location, distance, velocity

示例数据如下:

ID,timestamp,latitude,longitude
3,6/9/2017 22:20,38.7953326,77.0088833  
1,5/5/2017 13:10,38.8890106,77.0500613
2,2/10/2017 16:23,40.7482494,73.9841913
1,5/5/2017 12:35,38.9206015,77.2223287
3,6/10/2017 10:00,42.3662109,71.0209426
1,5/5/2017 20:00,38.8974155,77.0368333
2,2/10/2017 7:30,38.8514261,77.0422981
3,6/9/2017 10:20,38.9173461,77.2225527
2,2/10/2017 19:51,40.7828687,73.9675438
3,6/10/2017 6:42,38.9542676,77.4496951
1,5/5/2017 16:35,38.8728748,77.0077629
2,2/10/2017 10:00,40.7769311,73.8761546

最佳答案

看来你可以使用 pandas 的魔力.

读取数据

使用 read_csv() 从 csv 文件创建 pandas dataframe 很容易功能:

import pandas as pd
df = pd.read_csv(filename)

根据您的示例数据,这将创建以下 dataframe:

    ID        timestamp   latitude  longitude
0    3   6/9/2017 22:20  38.795333  77.008883
1    1   5/5/2017 13:10  38.889011  77.050061
2    2  2/10/2017 16:23  40.748249  73.984191
3    1   5/5/2017 12:35  38.920602  77.222329
4    3  6/10/2017 10:00  42.366211  71.020943
5    1   5/5/2017 20:00  38.897416  77.036833
6    2   2/10/2017 7:30  38.851426  77.042298
7    3   6/9/2017 10:20  38.917346  77.222553
8    2  2/10/2017 19:51  40.782869  73.967544
9    3   6/10/2017 6:42  38.954268  77.449695
10   1   5/5/2017 16:35  38.872875  77.007763
11   2  2/10/2017 10:00  40.776931  73.876155

转换时间戳列

Pandas(和一般的 Python)拥有广泛的日期和时间操作库。但首先,您需要通过将时间戳列(字符串)转换为日期时间对象来准备数据。我假设您的数据在 format"MM/DD/YYYY"(因为您没有指定)。

df['timestamp'] = pd.to_datetime(df['timestamp'], format='%m/%d/%Y %H:%M')

辅助函数

您将必须定义一些函数来计算距离和速度。 Haversine 距离函数改编自 this answer .

from math import sin, cos, sqrt, atan2, radians

def getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2):
    R = 6371 # Radius of the earth in km
    dLat = radians(lat2-lat1)
    dLon = radians(lon2-lon1)
    rLat1 = radians(lat1)
    rLat2 = radians(lat2)
    a = sin(dLat/2) * sin(dLat/2) + cos(rLat1) * cos(rLat2) * sin(dLon/2) * sin(dLon/2) 
    c = 2 * atan2(sqrt(a), sqrt(1-a))
    d = R * c # Distance in km
    return d

def calc_velocity(dist_km, time_start, time_end):
    """Return 0 if time_start == time_end, avoid dividing by 0"""
    return dist_km / (time_end - time_start).seconds if time_end > time_start else 0

制作一些中间变量

我们想要计算每行的半正弦函数,但我们需要来自每组第一行的一些信息。幸运的是,pandas 使用 sort_values() 使这一切变得简单, groupby()transform() .

以下代码创建了 3 个新列,每个列用于每个 ID 的初始纬度、经度和时间。

# First sort by ID and timestamp:
df = df.sort_values(by=['ID', 'timestamp'])

# Group the sorted dataframe by ID, and grab the initial value for lat, lon, and time.
df['lat0'] = df.groupby('ID')['latitude'].transform(lambda x: x.iat[0])
df['lon0'] = df.groupby('ID')['longitude'].transform(lambda x: x.iat[0])
df['t0'] = df.groupby('ID')['timestamp'].transform(lambda x: x.iat[0])

应用函数

# create a new column for distance
df['dist_km'] = df.apply(
    lambda row: getDistanceFromLatLonInKm(
        lat1=row['latitude'],
        lon1=row['longitude'],
        lat2=row['lat0'],
        lon2=row['lon0']
    ),
    axis=1
)

# create a new column for velocity
df['velocity_kmps'] = df.apply(
    lambda row: calc_velocity(
        dist_km=row['dist_km'],
        time_start=row['t0'],
        time_end=row['timestamp']
    ),
    axis=1
)

结果

>>> print(df[['ID', 'timestamp', 'latitude', 'longitude', 'dist_km', 'velocity_kmps']])

    ID           timestamp   latitude  longitude     dist_km  velocity_kmps
3    1 2017-05-05 12:35:00  38.920602  77.222329    0.000000       0.000000
1    1 2017-05-05 13:10:00  38.889011  77.050061   15.314742       0.007293
10   1 2017-05-05 16:35:00  38.872875  77.007763   19.312148       0.001341
5    1 2017-05-05 20:00:00  38.897416  77.036833   16.255868       0.000609
6    2 2017-02-10 07:30:00  38.851426  77.042298    0.000000       0.000000
11   2 2017-02-10 10:00:00  40.776931  73.876155  344.880549       0.038320
2    2 2017-02-10 16:23:00  40.748249  73.984191  335.727502       0.010498
8    2 2017-02-10 19:51:00  40.782869  73.967544  339.206320       0.007629
7    3 2017-06-09 10:20:00  38.917346  77.222553    0.000000       0.000000
0    3 2017-06-09 22:20:00  38.795333  77.008883   22.942974       0.000531
9    3 2017-06-10 06:42:00  38.954268  77.449695   20.070609       0.000274
4    3 2017-06-10 10:00:00  42.366211  71.020943  648.450485       0.007611

从这里开始,我将留给您弄清楚如何获取每个 ID 的最后一个条目。

关于python - 计算时间顺序坐标之间的距离和速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48430053/

相关文章:

android - 从 Android 上的 GPS 供应商获取*粗略*位置

python - 在 Google App Engine 上用 Python 计算城市之间的距离并基于 GeoPT 查找周边城市

python - 获得矩阵乘法的更快方法

distance - 获取 DICOM 中切片之间的距离

python - 包含 pandas 数据框的数组和矩阵的字典列表

android - 如何以编程方式禁用/启用 root Android 上的 GPS?

python - 如何在 pandas.to_latex() 生成的 LaTeX 表中自动换行文本?

c - 解析 GPS (GPGGA) 会导致奇怪的行为

python - Nose 测试 : how to show customized logging

python - 1.2.x 中的 Django ManyToMany 内联排序