Одним из способов является вычисление матрицы полного расстояния, затем melt
и ее агрегирование с использованием nsmallest
, которое возвращает индекс вместе со значением:
from scipy.spatial.distance import cdist
def nearest_record(XA, XB):
"""Get the nearest record in XA for each record in XB.
Args:
XA: DataFrame. Each record is matched against the nearest in XB.
XB: DataFrame.
Returns:
DataFrame with columns for id_A (from XA), id_B (from XB), and dist.
Each id_A maps to a single id_B, which is the nearest record from XB.
"""
dist = pd.DataFrame(cdist(XA, XB)).reset_index().melt('index')
dist.columns = ['id_A', 'id_B', 'dist']
# id_B is sometimes returned as an object.
dist['id_B'] = dist.id_B.astype(int)
dist.reset_index(drop=True, inplace=True)
nearest = dist.groupby('id_A').dist.nsmallest(1).reset_index()
return nearest.set_index('level_1').join(dist.id_B).reset_index(drop=True)
Это показывает, что id_B
2является ближайшей записью к каждой из трех записей в XA
:
nearest_record(XA, XB)
id_A dist id_B
0 0 5.099020 2
1 1 4.472136 2
2 2 4.242641 2
Однако, поскольку это включает в себя вычисление матрицы полного расстояния, она будет медленной или потерпит неудачу, когда XA
и XB
большой.Альтернатива, которая вычисляет ближайшее для каждой строки, скорее всего, будет быстрее.