基于经纬度点最小距离为DataFrame分配聚类标签的实现问询
解决方法:为df2的点分配最近邻对应的clust标签
我来帮你搞定这个问题——你不需要手动逐个循环计算,我们可以用向量化运算或者专门的最近邻工具来高效完成,同时精准分配对应的聚类标签。下面给你两种实用的方案,分别适合不同的数据规模:
方法1:使用Scipy的cdist计算全量距离(适合中小规模数据)
这种方法直接计算df2每个点与df1所有点的距离,然后找到最小距离对应的clust值。
步骤示例:
首先我们先还原你的示例数据:
import pandas as pd from scipy.spatial.distance import cdist # 构造df1 df1 = pd.DataFrame({ 'clust': [1, 1, 2, 2, 3, 3], 'longitude': [77.62279999, 77.62517676, 77.62753442, 77.62753442, 77.62217671, 77.62217671], 'latitude': [12.95248389, 12.95027966, 12.93745478, 12.93745478, 12.93353553, 12.93353553] }) # 构造示例df2 df2 = pd.DataFrame({ 'longitude': [77.623, 77.627, 77.622], 'latitude': [12.951, 12.937, 12.934] })
接下来执行标签分配:
# 提取df1的坐标矩阵 df1_coords = df1[['longitude', 'latitude']].values # 提取df1的clust标签 df1_clust = df1['clust'].values # 计算df2与df1所有点的欧氏距离矩阵(shape: [df2行数, df1行数]) distance_matrix = cdist(df2[['longitude', 'latitude']].values, df1_coords, metric='euclidean') # 找到每个df2点对应的最小距离的索引 min_dist_indices = distance_matrix.argmin(axis=1) # 根据索引匹配对应的clust标签,添加到df2中 df2['assigned_clust'] = df1_clust[min_dist_indices]
运行后df2就会新增assigned_clust列,每个点都对应了df1中最近点的聚类标签。
方法2:使用Sklearn的NearestNeighbors(适合大规模数据)
如果你的df1和df2数据量很大,全量计算距离会非常耗时,这时候用NearestNeighbors的KD-Tree/Ball-Tree算法会高效很多,它会优化最近邻的搜索过程。
步骤示例:
import pandas as pd from sklearn.neighbors import NearestNeighbors # 同样先构造示例数据(和上面一致) df1 = pd.DataFrame({ 'clust': [1, 1, 2, 2, 3, 3], 'longitude': [77.62279999, 77.62517676, 77.62753442, 77.62753442, 77.62217671, 77.62217671], 'latitude': [12.95248389, 12.95027966, 12.93745478, 12.93745478, 12.93353553, 12.93353553] }) df2 = pd.DataFrame({ 'longitude': [77.623, 77.627, 77.622], 'latitude': [12.951, 12.937, 12.934] }) # 初始化最近邻模型,只找最近的1个点 nn_model = NearestNeighbors(n_neighbors=1, metric='euclidean') # 用df1的坐标训练模型 nn_model.fit(df1[['longitude', 'latitude']].values) # 查找df2每个点的最近邻索引 distances, indices = nn_model.kneighbors(df2[['longitude', 'latitude']].values) # 匹配clust标签,注意indices是二维数组,需要flatten成一维 df2['assigned_clust'] = df1['clust'].iloc[indices.flatten()].values
这个方法在数据量较大时,速度会比cdist快很多,而且代码同样简洁。
补充说明:
- 两种方法默认用的是欧氏距离,如果你的坐标是经纬度,需要计算球面距离的话,可以把
metric参数改成'haversine',但要注意把经纬度转换成弧度(用np.radians()),因为haversine距离的输入要求是弧度制的坐标。 - 如果df1中有重复点(比如你示例里clust2和3的重复点),这不影响结果,因为最近邻的索引会指向其中一个,对应的clust标签是一致的。
内容的提问来源于stack exchange,提问作者muni
相关产品推荐
相关产品推荐

