2017-10-20 139 views
0

你好我正在使用Python来计算用户走过的距离。我正在确定他们是否按速度走或不走。如果速度低于5米/秒,我会考虑走路。但是我很难做这个功能。你能帮我解决这个问题吗?到目前为止,我输入手动把所谓的“make_timestamped_loc”,并计算由被称为“total_dist”这是我的代码功能的距离另一个函数...计算距离的功能

import ctp17hw1 
dic_loc = [] 
def make_timestamped_loc(La, Lng, TS): 
    new_loc = {} 
    new_loc['latitude'] = La 
    new_loc['longitude'] = Lng 
    new_loc['timestamp'] = int(TS) 
    dic_loc.append(new_loc) 

make_timestamped_loc(37.481236, 126.952733, 1483196400) 
make_timestamped_loc(37.310045, 127.101255, 1408323255) 
make_timestamped_loc(37.383065, 126.672596, 1508322531) 
make_timestamped_loc(37.383065, 116.672596, 1444999230) 

# make_timestamped_loc(37.383065, 112.672596, 1444999230) #error sample 
print(dic_loc) 
def sort_locs(sortingDict): 
    newlist = sorted(sortingDict, key=lambda k: k['timestamp']) 
    for i in range(len(dic_loc) - 1, -1, -1): 
     dic_loc.remove(dic_loc[i]) 
    for i in range(len(newlist)): 
     for j in range(len(newlist)): 
      if (newlist[i]['timestamp'] == newlist[j]['timestamp'] 
       and (newlist[i]['latitude'] != newlist[j]['latitude'] or newlist[i]['longitude'] != newlist[j]['longitude']) 
       and i != j): 
       raise ValueError('There is duplicated location on same time!') 
     sortingDict.append(newlist[i]) 
sort_locs(dic_loc) 


def total_dist(sortedDict): 
     totalDist = 0; 
     for i in range(len(sortedDict) - 1): 
      sm = ctp17hw1.dist(sortedDict[i]["latitude"], sortedDict[i]["longitude"], sortedDict[i+1]["latitude"], sortedDict[i+1]["longitude"]) 
      totalDist = totalDist + sm 
     return totalDist 
total_dist(dic_loc) 
print(total_dist(dic_loc)) 

ctp17hw1是计算距离的其它文件。 因为Unix时间,我很困惑。 非常感谢您

+0

这些时间戳编号从哪里来? Unix时间戳记给出了自纪元以来的秒数。所以从1408323255到1483196400的时间大约是866.587326天。 –

+0

哦,时间戳实际上是我随机编辑的;;;所以你可以完全忽略它。对不起混淆 –

+0

好吧,这种混乱使得它难以理解你的目标:你能否提供一些准确的时间戳来检查我们自己的解决方案?此外,预期的产出也是受欢迎的! – FunkySayu

回答

0

使用Getting distance between two points based on latitude/longitudeIterate a list as pair (current, next) in Python我是能够建立这个问题的Python的方式提供的解决方案:

import itertools 

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

Location = namedtuple('Location', ['long', 'lat', 'time']) 
all_locations = [ 
    Location(lat=37.481236, long=126.952733, time=1488323400), 
    Location(lat=37.310045, long=127.101255, time=1488323255), 
    Location(lat=37.383065, long=126.672596, time=1488323531), 
    Location(lat=37.383065, long=116.672596, time=1488323230), 
] 


def distance(loc_a, loc_b): 
    """Extracted from: https://stackoverflow.com/questions/19412462""" 
    R = 6373.0 

    lat_a, lat_b = radians(loc_a.lat), radians(loc_b.lat) 
    long_a, long_b = radians(loc_a.long), radians(loc_b.long) 
    dlat = lat_b - lat_a 
    dlong = long_b - long_a 

    a = sin(dlat/2)**2 + cos(lat_a) * cos(lat_b) * sin(dlong/2) ** 2 
    c = 2 * atan2(sqrt(a), sqrt(1 - a)) 

    return R * c 


def pairwise(iterable): 
    """Extracted from: https://stackoverflow.com/questions/5434891""" 
    a, b = itertools.tee(iterable) 
    next(b, None) 
    return zip(a, b) 


sorted_locations = sorted(all_locations, key=lambda l: l.time) 
total_distance = sum(distance(a, b) for a, b in pairwise(sorted_locations)) 
delta_time = sorted_locations[-1].time - sorted_locations[0].time 
print(total_distance, delta_time, total_distance/delta_time) 

使用namedtuple不是强制性的,但我觉得这会简化代码。名为元组的FTR是简单的结构,只包含声明字段(这里是长,经度和时间)。

pairwise函数允许迭代2对列表(即当前和下一个元素)。通过在排序的位置列表上按时间使用它,我可以轻松评估距离。基本上:

sorted_locations = [l1, l2, l3] 
distances = [distance(a, b) for a, b in pairwise(sorted_locations)] 
# equivalent to [distance(l1, l2), distance(l2, l3)] 
total_distance = sum(distances) 

不使用中间列表将减少内存消耗(这与示例中不相关,与大型列表相关)。我也可以声明一个距离生成器(使用(distance(a, b) for ...)以及列表理解)。


注意我没有预先计算的经度/纬度,他们计算的2倍radians的名单的非极值元素。这可能会提高一点性能,但我最想保持简单的算法。