pandas 根据最近的坐标合并两个数据帧
pandas merge two dataframes based on nearest coordinates
我有两个数据框,它们由 x
、y
、val
列组成,其中(x
和 y
是笛卡尔坐标数据点)
例如
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
解释:
- 使用
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. ]])
- 使用
numpy.argmin
和iloc
获取距离另一个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]
- 使用
pandas.concat
形成所需的DataFrame。
注:
如果你有两个同样接近的点,这只会给你第一个。
我有两个数据框,它们由 x
、y
、val
列组成,其中(x
和 y
是笛卡尔坐标数据点)
例如
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
解释:
- 使用
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. ]])
- 使用
numpy.argmin
和iloc
获取距离另一个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]
- 使用
pandas.concat
形成所需的DataFrame。
注:
如果你有两个同样接近的点,这只会给你第一个。