我对2轴的数据有交叉识别问题,比如
A = array([['x0', 'y0', 'data0', 'data0'],
['x0', 'y0', 'data0', 'data0'],
['x0', 'y0', 'data0', 'data0']])
B = array([['x1', 'y1', 'data1', 'data1'],
['x1', 'y1', 'data1', 'data1'],
['x1', 'y1', 'data1', 'data1']])
我需要的是找到具有相同position
的2个列表的行。 position
需要被描述为distance
足够接近,即:
distance = acos(cos(y0)*cos(y1)*cos(x0-x1)+sin(y0)*sin(y1))
if(distance < 0.001):
position = True
目前,我使用如下代码:
from math import *
def distance(x1,y1,x2,y2):
a = acos(cos(y1)*cos(y2)*cos(x1-x2)+sin(y1)*sin(y2))
if(a < 0.001):
return True
else:
return False
f = open('cross-identification')
for i in range(len(A[0])):
for j in range(len(B[0])):
if(distance(A[0][i],A[1][i],B[0][j],B[1][j])==True):
print(A[0][i],A[1][i],A[2][i],B[2][j],A[3][i],B[3][j],file=f)
else:continue
没有几行可以,但问题是我有大量数据而且速度非常慢。有没有什么方法可以让它更快?
BTW我已阅读this,接近我想要的但我无法改变它。也许我可以从你那里得到一些帮助?
答案 0 :(得分:2)
为了避免使用昂贵的Haversine公式而且打开使用KDTrees的选项,我建议翻译为欧几里德坐标和距离。
def to_eucl_coords(lat, lon):
z = np.sin(lat)
x = np.sin(lon)*np.cos(lat)
y = np.cos(lon)*np.cos(lat)
return x, y, z
def to_eucl_dist(sphdist):
return 2*np.arcsin(sphdist/2)
KDTrees易于使用,这是一个可以帮助你入门的骨架。
from scipy.spatial import cKDTree as KDTree
eucl_1 = np.c_[to_eucl_coords(lat1, lon1)]
eucl_2 = np.c_[to_eucl_coords(lat2, lon2)]
t1, t2 = KDTree(eucl_1), KDTree(eucl2)
neighbors = t1.query_ball_tree(t2, threshold)
答案 1 :(得分:0)
这是性能问题。你有很多低悬的果实可以大大改善你的距离功能。
而不是acos(x) < eps
使用x > 1 - (eps**2)/2
为您节省了广泛的acos()
(由于Taylor扩展而有效),显然是预计算1 - (eps**2)/2
而不是计算cos(y0)
等4*len(A[0])*len(B[0])
次,预先计算它们只需2*(len(A[0])+len(B[0]))
次,如果A*B
变大,可以节省许多三次计算
在我看来,预先计算cos(x1-x2)
也是一个胜利,但我不是百分百肯定
这只是略微优化每个距离评估。我认为更大的问题是你的双循环正在进行N * M评估。理想情况下,您可以使用一些智能几何算法来减少该循环。 (参见例如Mark de Berg等人的Computational Geometry,Springer 2008)
但你的距离(公制)功能太奇怪了!我无法看到如何将(x,y)
转换为具有该指标函数的空间。我非常好奇这个距离函数的来源。
答案 2 :(得分:0)
这是一个典型的外部产品类型问题:比较两个向量的每个组合。
之前的答案是正确的,你的双循环正在扼杀效率。一个可能的答案是使用numpy
根据输入的大小,您可以使用meshgrid方法或(更复杂的)使用outer product的numpy通用函数。
对于前者,您可以尝试类似:
import numpy as np
A = [[1, 1],
[1, 3],
[3, 1],
[3, 3]]
B = [[1, 1],
[3, 1],
[1, 2],
[1, 3],
[3, 3]]
a_array = np.array(A)
b_array = np.array(B)
x0, x1 = np.meshgrid(a_array[:, 0], b_array[:, 0])
y0, y1 = np.meshgrid(a_array[:, 1], b_array[:, 1])
distance = np.arccos(np.cos(y0)*np.cos(y1)*np.cos(x0-x1)+np.sin(y0)*np.sin(y1))
good_pairs = np.nonzero(distance < 0.001)
print(distance)
print(good_pairs)
for b_ind, a_ind in zip(*good_pairs):
print('Entry {} of A ({}) matches entry {} of B ({})'.format(a_ind, A[a_ind], b_ind, B[b_ind]))