我正在寻找一种有效的方法来使用来自一个数据帧 (df1) 的单行变量对另一个数据帧 (df2) 中的每一行应用公式,然后找到此操作的最小值并存储来自df2,其中此最小值作为新数据帧 (df3) 出现。 给出了示例输入/输出。
df1
Index X1 Y1 Z1
1 3 6 4
2 7 2 1
3 4 7 3
df2
Index X2 Y2 Z2
1 2 4 1
2 5 3 2
3 7 1 5
申请公式:
d = math.sqrt((X2-X1)**2 + (Y2-Y1)**2 + (Z2-Z1)**2)
如果将此公式迭代应用于 df2,其中 (X1, Y1, Z1) 来自 df1 row1 并且 (X2, Y2, Z2) 来自 df2 中的每一行以给出。
[out]
Index d
1 3.741
2 4.123
3 6.481
由于 df2 第 1 行中的 (X2, Y2, Z2) 提供了最低的 d 值,因此该行将保存到 df3 中,然后对 df1 中的每一行重复该过程。
df3
Index X2 Y2 Z2
1 2 4 1
*注意,df1 和 df2 的长度不同。如果这个问题看起来冗长,我很抱歉,我只是想尽可能清楚。
答案 0 :(得分:1)
scipy.spatial.distance.cdist
可用于其默认欧几里得距离度量:
from scipy.spatial.distance import cdist
df3 = df2.iloc[cdist(df1, df2).argmin(axis=1)]
cdist
返回一个 (n1, n2)
形状的数组,其中 n1
和 n2
分别是 df1
和 df2
中的行数。然后我们查看每一行的最小距离的索引,看看是哪一行 df2
引起了它。 iloc
然后从 df2
中选择这些,
得到
>>> df3
X2 Y2 Z2
Index
1 2 4 1
2 5 3 2
1 2 4 1
中间结果:
>>> cdist(df1, df2)
# first row is your calculations in the question, for example
array([[3.74165739, 4.12310563, 6.4807407 ],
[5.38516481, 2.44948974, 4.12310563],
[4.12310563, 4.24264069, 7. ]])
>>> cdist(df1, df2).argmin(axis=1)
array([0, 1, 0], dtype=int64)
即df1
的第0行和第2行,选择df2
的第0行;对于 df1
的第一行,选择了 df2
的第一行(0 索引)。
# will keep the minimum distance rows' indices
min_inds = []
# foreach row of `df1`...
for row1 in df1.values:
# these will keep track of min so-far
min_dist = np.inf
min_ind = None
# foreach row of `df2`...
for j, row2 in enumerate(df2.values):
# squared distance
dist = ((row1 - row2) ** 2).sum()
# is less than minimum so far?
if dist < min_dist:
# then update min distance and index
min_dist = dist
min_ind = j
# one row of `df1` finished; save its corresponding row's index
min_inds.append(min_ind)
# Now we form `df3` with `iloc` as before
df3 = df2.iloc[min_inds]
给出相同的结果,但可能更节省内存。