You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加快DataFrame逐行循环筛选、匹配最近邻地块的运行速度

核心性能瓶颈

你的代码跑几个小时完全是可预见的,核心问题出在这几个地方:

  • 纯Python for循环逐行处理数万条主数据,循环本身的开销就非常高
  • 每次循环内多次执行SecondayLatLong.loc[SecondayLatLong['Index'] == xxx],这是全表扫描匹配,单次复杂度就是O(次数据集行数),叠加循环后时间复杂度直接爆炸
  • 所有筛选、排序、取值操作都是单条处理,完全没有利用pandas/numpy的向量化加速能力

最优优化方案(推荐,耗时可降到分钟甚至秒级)

不要提前生成完整的距离矩阵(数万x数十万的矩阵本身就要占几十GB内存,计算也极慢),直接用空间索引做批量K近邻查询:

import numpy as np
import pandas as pd
from sklearn.neighbors import BallTree

# 1. 提前做好次数据集的ID映射,后续取值O(1)
secondary = SecondayLatLong.set_index('Index')[['AssessedValue', 'YearHomeBuilt']]
# 2. 经纬度转弧度,适配BallTree的haversine距离计算
secondary_coords = np.radians(SecondayLatLong[['纬度列名', '经度列名']].values)
primary_coords = np.radians(primaryLatLong[['纬度列名', '经度列名']].values)

# 3. 对次数据集坐标建BallTree空间索引
tree = BallTree(secondary_coords, metric='haversine')
# 4. 距离阈值转弧度:地球半径约3958.8英里,所以rangez(单位英里)转弧度为 rangez/3958.8
radius = rangez / 3958.8
# 5. 批量查询所有主数据点的、在阈值范围内的最近邻居,自动按距离排序
distances, secondary_indices = tree.query_radius(
    primary_coords, 
    r=radius, 
    return_distance=True, 
    sort_results=True
)

# 6. 批量生成结果
result = []
for idx in range(len(primaryLatLong)):
    cur_dists = distances[idx]
    cur_indices = secondary_indices[idx]
    # 过滤掉距离小于0.001英里的
    valid_mask = cur_dists * 3958.8 > 0.001
    cur_dists = cur_dists[valid_mask]
    cur_indices = cur_indices[valid_mask]
    # 取前5个,不足补0
    row = [primaryLatLong['Index'][idx]]
    for n in range(5):
        if n < len(cur_dists):
            sec_idx = SecondayLatLong['Index'].iloc[cur_indices[n]]
            dist = cur_dists[n] * 3958.8
            val = secondary.loc[sec_idx, 'AssessedValue']
            year = secondary.loc[sec_idx, 'YearHomeBuilt']
            row.extend([
                sec_idx,
                f"{dist:.4f} Miles",
                f"${int(val):,}",
                int(year)
            ])
        else:
            row.extend([0,0,0,0])
    result.append(row)

# 7. 一次性转DataFrame
final_df = pd.DataFrame(result, columns=threeclosest.columns)

这个方案的核心是用BallTree的空间索引把近邻查询的复杂度从O(n*m)降到了O(n log m),数万主数据、数十万次数据的场景下,全程耗时一般不会超过1分钟。


如果你必须用已生成的距离矩阵优化

如果距离矩阵已经生成好不想重新计算,可以按下面的方式优化,也能提速10倍以上:

  1. 先提前做好次数据集的ID索引映射,和上面方案的第一步一样
  2. 把Dmatrix中不符合阈值(>rangez 或 <=0.001)的位置批量设置为无穷大
  3. 用np.argpartition批量取每行最小的5个值的索引,比逐行sort快数倍
  4. 批量取值拼接结果,不要逐行append Series

额外优化提示

  • 不要用裸except,最好指定具体的异常类型,避免隐藏实际运行错误
  • 永远不要逐行append到DataFrame,先把所有结果存在列表里最后一次性转DataFrame,能节省大量IO开销

内容的提问来源于stack exchange,提问作者Benzo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 04:15:00