How to calculate the midpoint of several geolocations in python

15,043

Solution 1

After the comments I received and comment from HERE

With coordinates that close to each other, you can treat the Earth as being locally flat and simply find the centroid as though they were planar coordinates. Then you would simply take the average of the latitudes and the average of the longitudes to find the latitude and longitude of the centroid.

lat = []
long = []
for l in L :
  lat.append(l[0])
  long.append(l[1])

sum(lat)/len(lat)
sum(long)/len(long)

-74.07461283333332, 40.76800886666667

Solution 2

Based on: https://gist.github.com/tlhunter/0ea604b77775b3e7d7d25ea0f70a23eb

Assume you have a pandas DataFrame with latitude and longitude columns, the next code will return a dictionary with the mean coordinates.

import math

x = 0.0
y = 0.0
z = 0.0

for i, coord in coords_df.iterrows():
    latitude = math.radians(coord.latitude)
    longitude = math.radians(coord.longitude)

    x += math.cos(latitude) * math.cos(longitude)
    y += math.cos(latitude) * math.sin(longitude)
    z += math.sin(latitude)

total = len(coords_df)

x = x / total
y = y / total
z = z / total

central_longitude = math.atan2(y, x)
central_square_root = math.sqrt(x * x + y * y)
central_latitude = math.atan2(z, central_square_root)

mean_location = {
    'latitude': math.degrees(central_latitude),
    'longitude': math.degrees(central_longitude)
    }

Solution 3

Considering that you are using signed degrees format (more), simple averaging of latitude and longitudes would create problems for even small regions near to antimeridian (i.e. + or - 180-degree longitude) due to discontinuity of longitude value at this line (sudden jump between -180 to 180).

Consider two locations whose longitudes are -179 and 179, their mean would be 0, which is wrong.

Solution 4

This link can be useful, first convert lat/lon into an n-vector, then find average. A first stab at converting the code into Python is below

import numpy as np
import numpy.linalg as lin

E = np.array([[0, 0, 1],
              [0, 1, 0],
              [-1, 0, 0]])

def lat_long2n_E(latitude,longitude):
    res = [np.sin(np.deg2rad(latitude)),
           np.sin(np.deg2rad(longitude)) * np.cos(np.deg2rad(latitude)),
           -np.cos(np.deg2rad(longitude)) * np.cos(np.deg2rad(latitude))]
    return np.dot(E.T,np.array(res))

def n_E2lat_long(n_E):
    n_E = np.dot(E, n_E)
    longitude=np.arctan2(n_E[1],-n_E[2]);
    equatorial_component = np.sqrt(n_E[1]**2 + n_E[2]**2 );
    latitude=np.arctan2(n_E[0],equatorial_component);
    return np.rad2deg(latitude), np.rad2deg(longitude)

def average(coords):
    res = []
    for lat,lon in coords:
        res.append(lat_long2n_E(lat,lon))
    res = np.array(res)
    m = np.mean(res,axis=0)
    m = m / lin.norm(m)
    return n_E2lat_long(m)
        

n = lat_long2n_E(30,20)
print (n)
print (n_E2lat_long(np.array(n)))

# find middle of france and libya
coords = [[30,20],[47,3]]
m = average(coords)
print (m)

enter image description here

Share:
15,043
mongotop
Author by

mongotop

BY DAY: Data Engineer. BY NIGHT: I like to hit the gym for a bit and cook some nice traditional Moroccan food. FOR FUN: camping during the weekend, watching movies in the theater and reading outdoors.

Updated on June 05, 2022

Comments

  • mongotop
    mongotop almost 2 years

    Is there's a library or a way to calculate the center point for several geolocations points? This is my list of geolocations based in New York and want to find the approximate midpoint geolocation

    L = [
         (-74.2813611,40.8752222),
         (-73.4134167,40.7287778),
         (-74.3145014,40.9475244),
         (-74.2445833,40.6174444),
         (-74.4148889,40.7993333),
         (-73.7789256,40.6397511)
        ]
    
  • mongotop
    mongotop almost 3 years
    Thank you @BBSysDyn. This is a wonderful explanation!