比较两个元组列表的欧几里德距离与较少的比较python

时间:2017-12-04 21:37:21

标签: python list tuples coordinates

我正在尝试计算两个元组列表的欧几里德距离,阈值为4。如果阈值小于特定值,则递增计数器。每个元组是该点的x,y,z坐标。无论如何,我可以降低list1与list2的比较..

  X = [ (1,2,3),(2,3,4), (4,5,6) ]
  Y = [ (1,2,2) , (3,4,5),(6,7,8) ]
  from math import sqrt
  dist_X = [ sqrt((p[0] - 0)**2 + (p[1] - 0)**2 + (p[2] - 0)**2) for p in X]
  dist_Y = [ sqrt((p[0] - 0)**2 + (p[1] - 0)**2 + (p[2] - 0)**2) for p in Y]
  for x in dist_X:
     print (x ,  [ i for i,y in enumerate(dist_Y) if abs(x-y) <= 4])

我在考虑首先使用原点(0,0,0)计算每个点的欧几里德距离,这样两个列表现在都包含彼此接近的点,但由于它的标量值不起作用。我正朝着正确的方向前进吗?

修改

   visited1 = [ (1,2,3),(2,3,4), (4,5,6) ]
   visited2   = [ (1,2,2) , (3,4,5),(6,7,8) ]
    def euclidean(a,b):
        return sqrt((a[0] - b[0])**2+(a[1]-b[1])**2+(a[2]-b[2])**2)
   comparison = 0
   for i,j in enumerate(visited2):
     for k,l in enumerate(visited1):
         if euclidean(visited2[i],visited1[k]) < 4:
                 count += 1
         comparison += 1

在这里,list1的每个元素都与list2中的每个元素进行比较。我想知道是否有一种方法可以最小化给定点(x,y,z)的比较?

2 个答案:

答案 0 :(得分:3)

有时加速的一个预计算是kd-trees。我对蛮力进行了快速测试,发现对于较大的列表,它们可以快得多:

# n = 10
# trees                 0.08512560 ms
# brute                 0.01425540 ms
# n = 100
# trees                 0.20338160 ms
# brute                 0.09876890 ms
# n = 1000
# trees                 6.40193820 ms
# brute                16.15429670 ms
# n = 10000
# trees               298.69653380 ms
# brute              1393.71134270 ms

代码:

import numpy as np
from scipy.spatial import cKDTree

import types
from timeit import timeit

def setup_data(n, k):
    data = {'d1': np.random.randint(0, 10, (n, 3)),
            'd2': np.random.randint(0, 10, (n, 3)),
            'mx': k}
    return data

def f_trees(d1, d2, mx):
    t1 = cKDTree(d1)
    t2 = cKDTree(d2)
    return t1.count_neighbors(t2, mx)

def f_brute(d1, d2, mx):
    dist2 = np.add.outer(np.einsum('ij,ij->i', d1, d1), np.einsum('ij,ij->i', d2, d2)) - 2*np.einsum('ij, kj', d1, d2)
    return np.count_nonzero(dist2 <= mx*mx)



for n in (10, 100, 1000, 10000):
    data = setup_data(n, 4)
    ref = np.array(f_trees(**data))
    print(f'n = {n}')
    for name, func in list(globals().items()):
        if not name.startswith('f_') or not isinstance(func, types.FunctionType):
            continue
        try:
            assert np.allclose(ref, func(**data))
            print("{:16s}{:16.8f} ms".format(name[2:], timeit(
                'f(**data)', globals={'f':func, 'data':data}, number=10)*100))
        except:
            print("{:16s} apparently failed".format(name[2:]))

答案 1 :(得分:0)

在2D中绘制它以查看它的外观。与原点距离大致相同的点必然彼此接近 - 在那里你有三角不等式。例如,比较点(0,10),(0,11)和(-8,-6)。他们来自原点的所有10-11个单位,但最后一个远不及其他两个单位。

如果你想知道两个点是否彼此接近,你需要计算这两个点之间的距离,而不是到任意第三点的距离。这个问题的复杂性是二次的,而不是线性的。