我有2个数据帧df1和df2,它们具有不同的Latitutde和经度以及相应的地理位置。现在对于df1中的每个geohash,我想在数据帧df2中找到最接近的geohash。我不确定是否有办法比较地理位置。例如,对于df1中的id 121,df2中最接近的geohash为9muc3rr,df2中的id为122,最接近的geohash为9wv97m1。
Dataframe df1
Id Latitude Longitude Geohash
121 32.815130 -117.151695 9mudwju
122 37.920948 -108.005043 9wepwr3
Dataframe df2
Id Latitude Longitude Geohash
124 32.604187 -117.005745 9muc3rr
127 37.920948 -108.005043 9wv97m1
135 39.70122 -104.876976 9xj3v7q
128 38.844032 -104.718307 9wvscp6
答案 0 :(得分:0)
如果您可以稍微重新发明轮子,可以将(lat,lon)对转换为笛卡尔单位向量,然后只使用点积进行比较。由于点积基本上是一个向量投影到另一个向量的度量,因此最接近1(最大值)的乘积将是两个向量之间的最佳匹配。
以下示例计算基于this answer。我将假设您在WGS84椭圆体上提供大地坐标(因为GPS使用的是这样),并且椭圆体上方的高度对于所有点都是零:
from math import radians, sin, cos
import numpy as np
# WGS 84 parameters. Any other ellipsoid can be plugged in by changing
# the following lines. All parameters are taken from Wikipedia at
# https://en.wikipedia.org/wiki/Geodetic_datum#Parameters_for_some_geodetic_systems
invFlat = 298.257222101 # Inverse flattening (1/f), unitless
# Derived parameters
e2 = 6694.37999014 # First eccentricity squared. Unitless. Can be computed from 2*f − f**2
# Note that the radius is irrelevant since we are going to
# normalize the result anyway.
def cartesianUnitVector(lat, lon, isdeg=True):
if isdeg:
lat, lon = radians(lat), radians(lon)
vec = np.array([
cos(lat) * cos(lon),
cos(lat) * sin(lon),
(1 - e2) * sin(lat)
])
norm = np.linalg.norm(vec)
return vec / norm
target = (32.815130, -117.151695)
candidates = [
(32.604187, -117.005745),
(37.920948, -108.005043),
(39.70122, -104.876976),
(38.844032, -104.718307)
]
max(candidates, key=lambda x: np.dot(cartesianUnitVector(*x), cartesianUnitVector(*target)))
可以在Wikipedia找到大地测量到ECEF的公式。该示例显示了如何操作可迭代的lat-lon对。我不确定如何将其改编为熊猫,但你的问题是关于如何进行比较,我想我已经为此提供了答案。我相信一旦你定义了转换函数和使用它的比较键,你就可以毫不费力地将它应用到pandas了。