Created
December 14, 2024 04:56
-
-
Save chawza/6e0c019c27f785b7795f7fe4e6b1b58a to your computer and use it in GitHub Desktop.
Python get geopoint (latitude, longitude) distance using numpy
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
using numpy on 1000 samples running 100_000 loops each case will result on more than 3 times the speed
Result difference
both output difference is really small
Output