pandas 根据最近的坐标合并两个数据帧

pandas merge two dataframes based on nearest coordinates

我有两个数据框,它们由 xyval 列组成,其中(xy 是笛卡尔坐标数据点) 例如

df1

x y    val
----------
0 0    1.1
1 1    1.2
0 5    1.3
df2

x   y       val
---------------
0   0.1     2.1
1   1.3     2.2
1.1 5       2.3
0   0       2.5

它们的长度可以不同

我想根据最接近的对应数据点合并这些,给我这样的东西

val1      val2
---------------
1.1       2.1
1.2       2.2
1.3       2.3
1.1       2.5

我试过的

我已将数据框转换为坐标列表和值列表,然后使用 scipy.spatial.KDTree 找到最近的邻居,但这非常低效并且需要很长时间才能完成(数据帧有超过 30k 行)。

x = []
y = []

for idx, coord in enumerate(var1Coords):

    if var1Vals[idx] is None:
        continue
    distance, index = spatial.KDTree(var2Coords).query(coord)
    if var2Vals[index] is None:
        continue

    y.append(var2Vals[index])
    x.append(var1Vals[idx])

如果任何人有任何方法只用 pandas(理想)或任何其他有效的方法来做到这一点,我将非常感谢关于尝试什么的指导。

您可以使用 scipy 中的 cdist:

解决方案:

import numpy as np
from scipy.spatial.distance import cdist

output = pd.DataFrame()
output["val1"] = pd.Series([df1["val"].iloc[np.argmin(x)] for x in cdist(df2[["x", "y"]], df1[["x","y"]])])
output["val2"] = df2["val"]

>>> output
   val1  val2
0   1.1   2.1
1   1.2   2.2
2   1.3   2.3
3   1.1   2.5

解释:

  1. 使用cdist获取距离矩阵:
>>> cdist(df2[["x", "y"]], df1[["x","y"]])
array([[0.1       , 1.3453624 , 4.9       ],
       [1.64012195, 0.3       , 3.83275358],
       [5.11957029, 4.0012498 , 1.1       ],
       [0.        , 1.41421356, 5.        ]])
  1. 使用numpy.argminiloc获取距离另一个DataFrame最近点的值:
>>> [df1["val"].iloc[np.argmin(x)] for x in cdist(df2[["x", "y"]], df1[["x","y"]])]
[1.1, 1.2, 1.3, 1.1]
  1. 使用pandas.concat形成所需的DataFrame。
注:

如果你有两个同样接近的点,这只会给你第一个。