2017-10-20 169 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的名單的非極值元素。這可能會提高一點性能,但我最想保持簡單的算法。