优化坐标匹配修改代码性能:百万级文件提速求助
暴力循环慢到爆炸?教你几招把3小时压缩到几秒!
兄弟,我太懂你这种双重循环卡死的痛苦了——30万×10万的循环量,纯暴力匹配相当于要做3000亿次判断,能跑3小时都算不错的了😅。咱们直接换思路,把O(n*m)的复杂度降到O(n)或者O(n log n),分分钟搞定!
最容易上手的优化:用集合做快速查找
核心思路是把第二个文件的坐标存成集合,这样判断某个坐标是否存在的时间复杂度是O(1),直接把原来的双重循环拆成两次单次遍历。
修改后的代码:
import numpy as np # 读取第一个文件,用numpy直接读更高效 l3 = np.loadtxt('first file.txt') # 把第二个文件的坐标转成元组,存进集合 match_coords = set() with open('second file.txt', 'r') as t2: for line in t2: split = line.split() coord = (float(split[0]), float(split[1]), float(split[2])) match_coords.add(coord) # 遍历第一个数组,检查坐标是否在集合中 for row in l3: if (row[0], row[1], row[2]) in match_coords: row[3] += 970000000 # 保存结果 np.savetxt("result file.txt", l3, fmt='%7.4f %7.4f %7.4f %10.3f')
这个版本应该能把时间从3小时压缩到几十秒以内,完全够用了。
更高效的numpy向量化方案(完全避免Python循环)
如果想追求极致速度,用numpy的向量化操作,把判断和修改都放到C层面执行,速度会更快:
import numpy as np # 读取两个文件 first_data = np.loadtxt('first file.txt') second_coords = np.loadtxt('second file.txt') # 把三维坐标转换成结构化数组,让numpy可以批量判断是否存在 first_coords_struct = first_data[:, :3].view('f8,f8,f8') second_coords_struct = second_coords.view('f8,f8,f8') # 生成匹配的布尔掩码 is_match = np.isin(first_coords_struct, second_coords_struct) # 批量修改第四列 first_data[is_match, 3] += 970000000 # 保存结果 np.savetxt("result file.txt", first_data, fmt='%7.4f %7.4f %7.4f %10.3f')
这个版本几乎没有Python层面的循环,全部是numpy的底层优化操作,处理30万行数据大概几秒就能搞定。
特殊情况:浮点数精度问题
如果你的坐标是计算出来的近似值(比如存在0.1和0.1000000001这种微小差异),直接用==或者集合匹配会失败,这时候可以用KD-Tree做最近邻搜索:
from scipy.spatial import KDTree import numpy as np first_data = np.loadtxt('first file.txt') second_coords = np.loadtxt('second file.txt') # 构建KD-Tree用于快速空间搜索 tree = KDTree(second_coords) # 搜索每个坐标的最近邻,获取距离和索引 distances, _ = tree.query(first_data[:, :3], k=1) # 设置一个精度阈值,比如1e-8,距离小于这个值就算匹配成功 match_mask = distances < 1e-8 # 修改第四列 first_data[match_mask, 3] += 970000000 np.savetxt("result file.txt", first_data, fmt='%7.4f %7.4f %7.4f %10.3f')
这个方案能处理有精度误差的坐标匹配,速度也比暴力循环快N倍。
内容的提问来源于stack exchange,提问作者Panagiotis Menachilis
相关产品推荐
相关产品推荐

