如何计算 python 中多个地理位置的中点
How to calculate the midpoint of several geolocations in python
是否有库或方法可以计算多个地理位置点的中心点?
这是我在纽约的地理位置列表,想找到大致的中点地理位置
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)
]
在 comments
之后我收到了 HERE
的评论
使用 close to each other
的坐标,您可以将地球视为局部平坦的,并简单地找到质心,就好像它们是平面坐标一样。然后,您只需取纬度的平均值和经度的 average
即可找到 centroid
.
的 latitude
和 longitude
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
考虑到您使用的是有符号度数格式 (more),即使是靠近反子午线(即 + 或 - 180 度经度)的小区域,由于不连续性,纬度和经度的简单平均也会产生问题这条线的经度值(在 -180 到 180 之间突然跳跃)。
考虑经度为 -179 和 179 的两个位置,它们的平均值为 0,这是错误的。
基于:https://gist.github.com/tlhunter/0ea604b77775b3e7d7d25ea0f70a23eb
假设您有一个 pandas 包含纬度和经度列的 DataFrame,下一个代码将 return 一个包含平均坐标的字典。
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)
}
这个link会有用,先把lat/lon转成n向量,再求平均值。第一次尝试将代码转换为 Python
低于
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)
我想改进@BBSysDyn 的回答。
如果计算一侧有额外顶点的多边形的中心,则平均计算可能会有偏差。因此 average
函数可以替换为质心计算解释 here
def get_centroid(points):
x = points[:,0]
y = points[:,1]
# Solving for polygon signed area
A = 0
for i, value in enumerate(x):
if i + 1 == len(x):
A += (x[i]*y[0] - x[0]*y[i])
else:
A += (x[i]*y[i+1] - x[i+1]*y[i])
A = A/2
#solving x of centroid
Cx = 0
for i, value in enumerate(x):
if i + 1 == len(x):
Cx += (x[i]+x[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
else:
Cx += (x[i]+x[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
Cx = Cx/(6*A)
#solving y of centroid
Cy = 0
for i , value in enumerate(y):
if i+1 == len(x):
Cy += (y[i]+y[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
else:
Cy += (y[i]+y[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
Cy = Cy/(6*A)
return Cx, Cy
注意:如果是多边形或2个以上的点,必须列出它们,以便绘制多边形或形状。
是否有库或方法可以计算多个地理位置点的中心点? 这是我在纽约的地理位置列表,想找到大致的中点地理位置
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)
]
在 comments
之后我收到了 HERE
使用 close to each other
的坐标,您可以将地球视为局部平坦的,并简单地找到质心,就好像它们是平面坐标一样。然后,您只需取纬度的平均值和经度的 average
即可找到 centroid
.
latitude
和 longitude
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
考虑到您使用的是有符号度数格式 (more),即使是靠近反子午线(即 + 或 - 180 度经度)的小区域,由于不连续性,纬度和经度的简单平均也会产生问题这条线的经度值(在 -180 到 180 之间突然跳跃)。
考虑经度为 -179 和 179 的两个位置,它们的平均值为 0,这是错误的。
基于:https://gist.github.com/tlhunter/0ea604b77775b3e7d7d25ea0f70a23eb
假设您有一个 pandas 包含纬度和经度列的 DataFrame,下一个代码将 return 一个包含平均坐标的字典。
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)
}
这个link会有用,先把lat/lon转成n向量,再求平均值。第一次尝试将代码转换为 Python 低于
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)
我想改进@BBSysDyn 的回答。
如果计算一侧有额外顶点的多边形的中心,则平均计算可能会有偏差。因此 average
函数可以替换为质心计算解释 here
def get_centroid(points):
x = points[:,0]
y = points[:,1]
# Solving for polygon signed area
A = 0
for i, value in enumerate(x):
if i + 1 == len(x):
A += (x[i]*y[0] - x[0]*y[i])
else:
A += (x[i]*y[i+1] - x[i+1]*y[i])
A = A/2
#solving x of centroid
Cx = 0
for i, value in enumerate(x):
if i + 1 == len(x):
Cx += (x[i]+x[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
else:
Cx += (x[i]+x[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
Cx = Cx/(6*A)
#solving y of centroid
Cy = 0
for i , value in enumerate(y):
if i+1 == len(x):
Cy += (y[i]+y[0]) * ( (x[i]*y[0]) - (x[0]*y[i]) )
else:
Cy += (y[i]+y[i+1]) * ( (x[i]*y[i+1]) - (x[i+1]*y[i]) )
Cy = Cy/(6*A)
return Cx, Cy
注意:如果是多边形或2个以上的点,必须列出它们,以便绘制多边形或形状。