Python列表通过特定方程进行交叉识别(重叠?)

时间:2018-04-16 09:22:39

标签: python numpy match overlap

我对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,接近我想要的但我无法改变它。也许我可以从你那里得到一些帮助?

3 个答案:

答案 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)

这是性能问题。你有很多低悬的果实可以大大改善你的距离功能。

  1. 而不是acos(x) < eps使用x > 1 - (eps**2)/2为您节省了广泛的acos()(由于Taylor扩展而有效),显然是预计算1 - (eps**2)/2

    < / LI>
  2. 而不是计算cos(y0)4*len(A[0])*len(B[0])次,预先计算它们只需2*(len(A[0])+len(B[0]))次,如果A*B变大,可以节省许多三次计算

  3. 在我看来,预先计算cos(x1-x2)也是一个胜利,但我不是百分百肯定

  4. 这只是略微优化每个距离评估。我认为更大的问题是你的双循环正在进行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]))