0

Hello I am using Python to calculate the distance that user walked. I am determining whether they walked or not by speed. If there speed was slower than 5m/s, they I will consider as walking. But I am having trouble making this function. Could you help me out how to make function for this? So far my input is manually put another function called "make_timestamped_loc" and calculating the distance by function called "total_dist" Here is my code...

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 is another file for calculating the distance. I am confusing because of Unix time. Thank you very much

  • Where do those timestamp numbers come from? A Unix timestamp gives the number of seconds since the epoch. So the time span from 1408323255 to 1483196400 is around 866.587326 days. – PM 2Ring Oct 20 '17 at 10:20
  • Oh timestamps are actually edited by me randomly;;; so u can ignore it perfectly. sorry for confusion – Hyun Mo Luke Yang Oct 20 '17 at 10:23
  • Well, this confusion makes it harder to understand your goal: could you provide us some accurate timestamps for checking our own solutions? Also, expected outputs are welcome too! – FunkySayu Oct 20 '17 at 10:46

1 Answers1

0

Using solutions provided in Getting distance between two points based on latitude/longitude and Iterate a list as pair (current, next) in Python I was able to build a Pythonic approach of this problem:

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)

Using namedtuple is not mandatory, but I felt like it would simplify the code. FTR named tuple are simple structures only containing declared fields (here long, lat and time).

The pairwise function allows to iterate over 2 pairs of a list (i.e. current and next element). By using it on the sorted location list by time, I can easily evaluate the distance. Basically:

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)

Not using intermediate list will reduce memory consumption (which is irrelevant in the example, relevant for large lists). I could also declare a generator of distance (using (distance(a, b) for ...) insteand of a list comprehension).


Notice I did not pre-compute radians of long/lat, and they are computed 2 times for non-extrem elements of the list. This could be a little performance improvement but I mostly wanted to keep the algorithm simple here.

FunkySayu
  • 7,641
  • 10
  • 38
  • 61