Skip to content

Instantly share code, notes, and snippets.

@chawza
Created December 14, 2024 04:56
Show Gist options
  • Save chawza/6e0c019c27f785b7795f7fe4e6b1b58a to your computer and use it in GitHub Desktop.
Save chawza/6e0c019c27f785b7795f7fe4e6b1b58a to your computer and use it in GitHub Desktop.
Python get geopoint (latitude, longitude) distance using numpy
from math import radians, cos, sin, asin, sqrt
import numpy as np
import random
import time
from functools import wraps
import time
from functools import wraps
def get_lat():
return random.uniform(-90, 90)
def get_long():
return random.uniform(-180, 180)
def benchmark(function):
@wraps(function)
def wrapper(*args, **kwargs):
times = []
res = None
N_times = 100_000
for _ in range(100_000):
start = time.time()
res = function(*args, **kwargs)
end = time.time()
delta = end - start
times.append(delta)
total = sum(times)
avg = total / N_times
print(f'total: {sum(times):.6f}')
print(f'avg: {avg:.6f}')
return res
return wrapper
def get_distance(start_point: tuple[float, float], end_point: tuple[float, float]) -> float:
"""
Calculate the distance between two geographical locations in kilometers.
:param start_point: A tuple containing the latitude and longitude of the starting point.
:param end_point: A tuple containing the latitude and longitude of the ending point.
:return: The distance between the two points in kilometers.
"""
# Convert degrees to radians
start_lat = radians(start_point[0])
start_lon = radians(start_point[1])
end_lat = radians(end_point[0])
end_lon = radians(end_point[1])
# Haversine formula
dlon = end_lon - start_lon
dlat = end_lat - start_lat
a = sin(dlat / 2) ** 2 + cos(start_lat) * cos(end_lat) * sin(dlon / 2) ** 2
c = 2 * asin(sqrt(a))
# Calculate distance in kilometers
earth_radius = 6371
distance = earth_radius * c
return distance
def get_distances_multiple(start_point: tuple[float, float], end_points: list[tuple[float, float]]) -> np.array:
"""
Calculate the distances between a starting point and multiple ending points in kilometers.
:param start_point: A tuple containing the latitude and longitude of the starting point.
:param end_points: A list of tuples containing the latitude and longitude of the ending points.
:return: An array of distances between the starting point and each ending point in kilometers.
"""
# Convert degrees to radians
start_lat = radians(start_point[0])
start_lon = radians(start_point[1])
end_lats = np.array([radians(end_point[0]) for end_point in end_points])
end_lons = np.array([radians(end_point[1]) for end_point in end_points])
# Haversine formula
dlon = np.subtract(end_lons, start_lon)
dlat = np.subtract(end_lats, start_lat)
a = np.sin(dlat / 2) ** 2 + np.cos(start_lat) * np.cos(end_lats) * np.sin(dlon / 2) ** 2
c = 2 * np.asin(np.sqrt(a))
# Calculate distance in kilometers
earth_radius = 6371
distances = earth_radius * c
return distances
def main():
points = [
(get_lat(), get_long())
for _ in range(1000)
]
target = random.choice(points)
@benchmark
def test1():
result_1 = [get_distance(target, a) for a in points]
return result_1
@benchmark
def test2():
result_2 = get_distances_multiple(target, points)
return result_2
res_1 = test1()
res_2 = test2()
comp = res_1 == res_2
print(f'Same: ', len(list(_ for _ in comp if _ == True)))
diff_values = [(a, b) for a,b in zip(res_1, res_2) if a != b]
print(f'Difference: ', len(diff_values))
for a, b in diff_values:
print(f'{a:>20} {b:>20}')
if __name__ == '__main__':
main()
@chawza
Copy link
Author

chawza commented Dec 14, 2024

using numpy on 1000 samples running 100_000 loops each case will result on more than 3 times the speed

test using 12 thread CPU on python 3.13

Result difference

both output difference is really small

Output

total: 39.105560
avg: 0.000391
total: 12.073333
avg: 0.000121
Same:  939
Difference:  61
  4019.8039494752747    4019.803949475274
   12482.84946058726   12482.849460587262
  12534.764430587144   12534.764430587145
   7419.510240836255    7419.510240836256
      8715.623861802    8715.623861802002
   2291.797794130426   2291.7977941304257
  2065.1733940660497   2065.1733940660492
   10417.83588696262   10417.835886962623
   4453.101639986655    4453.101639986654
   5289.839410252898    5289.839410252897
   5152.742467427853    5152.742467427852
  10650.013332529252   10650.013332529254
  12028.308869885308    12028.30886988531
  13010.517835318642   13010.517835318644
   5088.634112011851     5088.63411201185
    9707.42561328906    9707.425613289062
  12669.021968488569    12669.02196848857
  12551.366221413202   12551.366221413204
   6873.518667848883    6873.518667848884
    4732.25814558697   4732.2581455869695
   8777.083427351568     8777.08342735157
  5686.2521433851725    5686.252143385172
   7072.658746711936    7072.658746711938
  10353.263218412854   10353.263218412856
   10226.00887133644   10226.008871336442
  13258.933686032498   13258.933686032502
   3912.835135978616    3912.835135978615
  12726.834874664613   12726.834874664615
  12879.302878995322   12879.302878995326
   8536.840719536458     8536.84071953646
   8191.189192851884    8191.189192851886
   4832.385216713925    4832.385216713924
   8640.341974049225    8640.341974049226
  10999.299636820564   10999.299636820566
     8913.2232963992    8913.223296399201
  1734.5768743404603   1734.5768743404599
  16228.764792938311   16228.764792938313
   7067.447714377607   7067.4477143776085
  12852.021774024139    12852.02177402414
  8167.7580865571845    8167.758086557185
   5027.732809654282   5027.7328096542815
   10072.57626269732   10072.576262697321
   6686.854850518373    6686.854850518374
   7001.344333937947    7001.344333937948
   7342.428959274666    7342.428959274668
  12414.206719352569    12414.20671935257
  12318.861731905145   12318.861731905146
   6973.942080922058     6973.94208092206
    2781.22123201293   2781.2212320129297
  11775.390044802984   11775.390044802985
   18154.91811723468   18154.918117234683
   5843.884247789494    5843.884247789493
  12554.584967563578    12554.58496756358
   6371.669544140324   6371.6695441403235
  3707.8584459425483   3707.8584459425474
  2547.9968405014633    2547.996840501463
  15747.205012551809   15747.205012551813
   8149.077795117095    8149.077795117097
  18022.879459418094   18022.879459418098
   6401.227148425127    6401.227148425125
    8771.42559179078    8771.425591790781

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment