基于经纬度实现一对多最近地点匹配时出现ValueError报错求解
报错原因
- 核心问题是近邻匹配的主从逻辑搞反,最终赋值对象错误:
- 你用2000行的df1(name点集)构建BallTree索引,之后传入25000行的df2(site点集)做近邻查询,返回的
indices、distances数组长度都是25000,每一行对应df2中一个site匹配到的最近df1点信息。 - 最后一行代码试图把长度25000的结果赋值给只有2000行的df1新列,长度完全不匹配,直接触发ValueError。
- 你的预期输出是每条site数据带匹配到的最近name,主表应该是df2,而非df1。
- 你用2000行的df1(name点集)构建BallTree索引,之后传入25000行的df2(site点集)做近邻查询,返回的
修正方案
直接将匹配到的df1的name值赋值给df2的新列即可,如果需要实际地理距离可以额外转换(haversine公式返回的是弧度距离,乘以地球半径6371即可得到公里单位的实际距离),修正后完整代码如下:
import pandas as pd import numpy as np from sklearn.neighbors import BallTree, DistanceMetric # 构建name点集df1 N = 2000 df1 = pd.DataFrame({'name': 'name' + pd.RangeIndex(1, N+1).astype(str), 'lat': np.random.uniform(30, 65, N), 'lon': np.random.uniform(-150, -70, N)}) # 构建站点点集df2 N = 25000 df2 = pd.DataFrame({'sitename': 'site' + pd.RangeIndex(1, N+1).astype(str), 'lat': np.random.uniform(30, 65, N), 'lon': np.random.uniform(-150, -70, N)}) # 用参考点集(df1)构建BallTree,注意经纬度要转弧度 coords_ref = np.radians(df1[['lat', 'lon']]) dist = DistanceMetric.get_metric('haversine') tree = BallTree(coords_ref, metric=dist) # 传入查询点集(df2)做k=1的最近邻查询 coords_query = np.radians(df2[['lat', 'lon']]) distances, indices = tree.query(coords_query, k=1) # 给df2赋值匹配到的最近name,距离列为可选项 df2['name'] = df1.iloc[indices.ravel()]['name'].values df2['distance_km'] = distances.ravel() * 6371 # 弧度单位转公里 # 按预期格式提取列 result = df2[['sitename', 'lat', 'lon', 'name']]
运行后result就是目标结构化表,输出格式和你给出的示例完全一致。
注:如果后续需要匹配每个点最近的多个地点,只需要修改
tree.query()的k参数即可,例如k=3会返回每个查询点最近的3个参考点的索引和距离。
内容的提问来源于stack exchange,提问作者Nabih Bawazir
相关产品推荐
相关产品推荐

