如何为含XY坐标的DataFrame添加基于最近固定点的分类列?
嘿,这个需求很常见,而且完全不用嵌套循环就能高效搞定!嵌套循环不仅代码繁琐,数据量大的时候还会慢得让人头疼,咱们用Pandas和NumPy的向量化操作来解决,既简洁又高效。
解决方案:用向量化操作替代嵌套循环
首先先把你的数据定义好(方便复现测试):
import pandas as pd import numpy as np # 你的df1数据 df1 = pd.DataFrame({ 'X': [224, 258, 225, 257, 226, 257, 226, 257, 224, 258], 'Y': [234, 232, 235, 232, 235, 232, 235, 232, 234, 232] }) # 你的固定座位列表,转成numpy数组方便计算 seats = np.array([[260, 165], [315, 165], [370, 165], [423, 165], [485, 200], [420, 240], [370, 240], [315, 240], [260, 240], [200,200]])
接下来分三步完成需求:
步骤1:计算每个点到所有座位的距离(向量化实现)
我们用欧氏距离的平方来比较(因为平方和开根号后的最小值索引完全一致,这样能省去开根号的计算开销,速度更快):
# 把df1的坐标转换成numpy数组 points = df1[['X', 'Y']].to_numpy() # 用广播机制计算每个点到所有座位的平方距离,结果形状为 (df1行数, 座位数) squared_distances = np.sum((points[:, np.newaxis] - seats)**2, axis=2)
步骤2:找到每个点对应的最小距离座位索引
对每一行(每个坐标点)取最小距离对应的座位索引:
min_indices = np.argmin(squared_distances, axis=1)
步骤3:生成分类列(seats0到seats9)
把索引转换成你需要的字符串格式:
df1['seat_category'] = 'seats' + min_indices.astype(str)
运行结果示例
执行完后,df1的前10行会是这样:
X Y seat_category 0 224 234 seats8 1 258 232 seats8 2 225 235 seats8 3 257 232 seats8 4 226 235 seats8 5 257 232 seats8 6 226 235 seats8 7 257 232 seats8 8 224 234 seats8 9 258 232 seats8
这是因为前10个点都离seats[8](坐标[260,240])最近,符合实际计算结果。
为什么不推荐嵌套循环?
- 效率极高:向量化操作是底层用C实现的,比Python层面的嵌套循环快几个数量级,当df1有成千上万行时,差距会非常明显。
- 代码简洁易读:几行代码就完成逻辑,维护和修改都很方便。
如果一定要用循环(非常不推荐),也能实现,但性能拉胯:
def find_closest_seat(row): min_dist = float('inf') closest_idx = -1 for idx, seat in enumerate(seats): dist = (row['X'] - seat[0])**2 + (row['Y'] - seat[1])**2 if dist < min_dist: min_dist = dist closest_idx = idx return f'seats{closest_idx}' df1['seat_category'] = df1.apply(find_closest_seat, axis=1)
内容的提问来源于stack exchange,提问作者user11999146
相关产品推荐
相关产品推荐

