首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算时序坐标之间的距离和速度

计算时序坐标之间的距离和速度
EN

Stack Overflow用户
提问于 2018-01-25 03:17:38
回答 1查看 7K关注 0票数 4

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

理想情况下,输出应该是第二个csv,如下所示:ID#, start_time, start_location, end_time, end_location, distance, velocity

示例数据如下:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-25 04:26:06

看起来你可以使用pandas的魔力。

读取数据

使用read_csv()函数可以很容易地从csv文件创建pandas dataframe

代码语言:javascript
复制
import pandas as pd
df = pd.read_csv(filename)

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

代码语言:javascript
复制
    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 )有很多用于日期和时间操作的库。但首先,您需要通过将时间戳列(字符串)转换为datetime对象来准备数据。我假设您的数据在format "MM/DD/YYYY"中(因为您没有指定)。

代码语言:javascript
复制
df['timestamp'] = pd.to_datetime(df['timestamp'], format='%m/%d/%Y %H:%M')

帮助器函数

你需要定义一些函数来计算距离和速度。哈维正弦距离函数是由this answer改编而来的。

代码语言:javascript
复制
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

制作一些中间变量

我们想要计算每一行的Haversine函数,但我们需要每组第一行的一些信息。幸运的是,pandas通过sort_values()groupby()transform()让这一切变得很容易。

下面的代码创建了3个新列,每个列分别表示每个ID的初始纬度、经度和时间。

代码语言:javascript
复制
# 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])

应用函数

代码语言:javascript
复制
# 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
)

结果

代码语言:javascript
复制
>>> 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的最后一个条目。

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48430053

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档