如何基于一个数据框中的两个键从另一个数据框中找到最接近的匹配项?

7
我有两个数据框正在处理。一个包含了许多地点和坐标(经度、纬度)。另一个是一个气象数据集,包含了来自世界各地的气象站和它们各自的坐标。我试图将每个位置与最近的气象站联系起来。气象站名字和我的位置名字不匹配。
我尝试着通过坐标的最接近匹配来进行链接,但是不知道从哪里开始。
我想到了使用以下代码: np.abs((location['latitude']-weather['latitude'])+(location['longitude']-weather['longitude']) 下面是每个数据框的示例:
位置...
Location   Latitude   Longitude Component  \
     A  39.463744  -76.119411    Active   
     B  39.029252  -76.964251    Active   
     C  33.626946  -85.969576    Active   
     D  49.286337   10.567013    Active   
     E  37.071777  -76.360785    Active   

天气...

     Station Code             Station Name  Latitude  Longitude
     US1FLSL0019    PORT ST. LUCIE 4.0 NE   27.3237   -80.3111
     US1TXTV0133            LAKEWAY 2.8 W   30.3597   -98.0252
     USC00178998                  WALTHAM   44.6917   -68.3475
     USC00178998                  WALTHAM   44.6917   -68.3475
     USC00178998                  WALTHAM   44.6917   -68.3475

输出将是位置数据帧上的一个新列,其中包含最接近匹配的站点名称。但是,我不确定如何循环遍历两者以完成此操作。任何帮助都将不胜感激。谢谢,Scott。

你能提供你的两个数据框的样本和期望输出吗? - Colonel Beauvel
1
除非你特别想用Python,否则你应该考虑使用postGIS查询,它们对于你的情况可以非常快速。 - CoderBC
已更新以反映每个数据框的示例和所需输出。 - sokeefe1014
@sokeefe1014,你尝试过专门用于地理数据处理的geopandas吗? - Joshua Baboo
2个回答

8
假设你有一个距离函数 dist,你想要最小化它:
def dist(lat1, long1, lat2, long2):
    return np.abs((lat1-lat2)+(long1-long2))

针对给定的位置,你可以按如下方式找到最近的站点:

lat = 39.463744
long = -76.119411
weather.apply(
    lambda row: dist(lat, long, row['Latitude'], row['Longitude']), 
    axis=1)

这将计算到所有气象站的距离。使用 idxmin,你可以找到最近的气象站名称:

distances = weather.apply(
    lambda row: dist(lat, long, row['Latitude'], row['Longitude']), 
    axis=1)
weather.loc[distances.idxmin(), 'StationName']

让我们把所有这些放在一个函数中:

def find_station(lat, long):
    distances = weather.apply(
        lambda row: dist(lat, long, row['Latitude'], row['Longitude']), 
        axis=1)
    return weather.loc[distances.idxmin(), 'StationName']

现在,您可以将其应用于“locations”数据帧,以获取所有最近的站点:
locations.apply(
    lambda row: find_station(row['Latitude'], row['Longitude']), 
    axis=1)

输出:

0         WALTHAM
1         WALTHAM
2    PORTST.LUCIE
3         WALTHAM
4    PORTST.LUCIE

2
对于两点之间的最小距离,应该是 sqrt((x1-x2)^2+(y1-y2)^2)。但是如果考虑到球面上的情况,公式会有所不同。 - CoderBC
感谢您的回答!我仍在最终确定以确保一切正常。我确实不得不更新dist函数,使其在纬度计算周围和经度计算周围都有np.abs。有时,当纬度偏差为正值而经度偏差为负值时,它们会抵消并给我一些完全不同的东西。除此之外,我相信它完美地工作了。那么,我只需将输出合并到索引上的位置数据框中吗? - sokeefe1014
@sokeefe1014 将结果包含在原始数据框中的最佳方法可能是类似于 locations['closest_station'] = locations.apply(lambda row: ..., axis=1) - IanS
非常感谢您! - sokeefe1014

0

所以我知道这可能有点凌乱,但我使用了类似的东西来匹配表格之间的遗传数据。它依赖于位置文件的经度和纬度与天气文件上的经纬度相差不超过5,但如果需要,这些数值可以进行更改。

rows=range(location.shape[0])
weath_rows = range(weather.shape[0])
for r in rows:
    lat = location.iloc[r,1]
    max_lat = lat +5
    min_lat = lat -5
    lon = location.iloc[r,2]
    max_lon = lon +5
    min_lon = lon -5
    for w in weath_rows:
        if (min_lat <= weather.iloc[w,2] <= max_lat) and (min_lon <= weather.iloc[w,3] <= max_lon):
            location['Station_Name'] = weather.iloc[w,1]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接