根据列值对之间的最接近匹配合并两个数据帧



我正试图根据列值对之间的匹配来合并两个数据帧。但是,从一个数据帧到下一个数据框架的列值并不精确。这些对是使用瑞士坐标系的坐标,但从每个df中稍微不同的参考点测量。

这个stackoverflow线程如何在Panda中找到2个不同数据帧中的2个点之间的距离?这似乎是一个相关的问题,但不幸的是,我没有完全理解答案。

我的数据示例:

df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],
'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],
'shape': ['square', 'square', 'triangle', 'circle']})
df1
Ecode            Ncode          shape
0   2669827.294     1261034.528     square
1   2669634.483     1262412.587     square
2   2669766.266     1261209.646     triangle
3   2669960.683     1262550.374     circle

df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],
'CoorN': [1262413, 1261211, 1261032, 1262550],
'color': ['purple', 'blue', 'blue', 'yellow']})
df2
CoorE       CoorN      color
0   2669636     1262413     purple
1   2669765     1261211     blue
2   2669827     1261032     blue
3   2669961     1262550     yellow

我有我想比较的数据与两组坐标(例如"形状"one_answers"颜色"(的位置。我想要的结果与最接近匹配的列对匹配:

CoorE       CoorN      color   shape
0   2669636     1262413     purple  square
1   2669765     1261211     blue    triangle
2   2669827     1261032     blue    square
3   2669961     1262550     yellow  circle

有办法做到这一点吗?我尝试过使用merge_asof,但意识到它不能对两个变量进行键控。我还看到了基于纬度和经度计算这一点的线程。我可以编写一个函数,将CoorE/CoorN和Ecode/Ncode视为x/y坐标,并计算一对坐标之间的距离(可能有更好的方法,但我对此并不熟悉(:

import math  
def calculateDistance(x1,y1,x2,y2):  
dist = math.sqrt((x2 - x1)**2 + (y2 - y1)**2)  
return dist  
print calculateDistance(x1, y1, x2, y2)

或者类似的东西,但不知道如何使用这种函数来比较和匹配基于最小距离的两个独立数据帧中的坐标对。真实的数据集也是大约300万个条目,我想知道什么是最不占用内存的方法

要使用库来计算距离,您需要在统一的系统上。从谷歌我相信你正在使用epsg:21781

  1. 首次使用pyproj标准化坐标系
  2. 颜色形状的笛卡尔乘积
  3. 使用geopy计算它们之间的距离
  4. 现在可以选择所需的结果行。例如,当按颜色形状分组时,我取了最接近的值
import pyproj, geopy.distance
df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],
'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],
'shape': ['square', 'square', 'triangle', 'circle']})
df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],
'CoorN': [1262413, 1261211, 1261032, 1262550],
'color': ['purple', 'blue', 'blue', 'yellow']})

# assuming this co-ord system https://epsg.io/21781 then mapping to https://epsg.io/4326
sc = pyproj.Proj("epsg:21781")
dc = pyproj.Proj("epsg:4326")
df1 = df1.assign(
shape_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["Ecode"], r["Ncode"]), axis=1)
)
df2 = df2.assign(
color_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["CoorE"], r["CoorN"]), axis=1)
)
(df1
.assign(foo=1)
.merge(df2.assign(foo=1), on="foo")
.assign(distance=lambda x: x.apply(lambda r: 
geopy.distance.geodesic(r["color_gps"], r["shape_gps"]).km, axis=1))
.sort_values("distance")
.groupby(["color","shape"]).agg({"distance":"first","CoorE":"first","CoorN":"first"})
)

更新为最近的合并

如果选择一个参考点来计算距离,则可以得到所需的距离。

import pyproj, geopy.distance
df1 = pd.DataFrame({'Ecode': [2669827.294, 2669634.483, 2669766.266, 2669960.683],
'Ncode': [1261034.528, 1262412.587, 1261209.646, 1262550.374],
'shape': ['square', 'square', 'triangle', 'circle']})
df2 = pd.DataFrame({'CoorE': [2669636, 2669765, 2669827, 2669961],
'CoorN': [1262413, 1261211, 1261032, 1262550],
'color': ['purple', 'blue', 'blue', 'yellow']})

# assuming this co-ord system https://epsg.io/21781 then mapping to https://epsg.io/4326
sc = pyproj.Proj("epsg:21781")
dc = pyproj.Proj("epsg:4326")
# pick a reference point for use in diatnace calcs
refpoint = pyproj.transform(sc, dc, df1.loc[0,["Ecode"]][0], df1.loc[0,["Ncode"]][0])
df1 = df1.assign(
shape_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["Ecode"], r["Ncode"]), axis=1),
distance=lambda x: x.apply(lambda r: geopy.distance.geodesic(refpoint, r["shape_gps"]).km, axis=1),
).sort_values("distance")
df2 = df2.assign(
color_gps=lambda x: x.apply(lambda r: pyproj.transform(sc, dc, r["CoorE"], r["CoorN"]), axis=1),
distance=lambda x: x.apply(lambda r: geopy.distance.geodesic(refpoint, r["color_gps"]).km, axis=1),
).sort_values("distance")
# no cleanup of columns but this works
pd.merge_asof(df1, df2, on="distance", direction="nearest")

最新更新