【问题标题】:Compare the Euclidean distance of two lists of tuples with fewer comparisons python用较少的比较python比较两个元组列表的欧几里得距离
【发布时间】:2017-12-04 21:37:20
【问题描述】:

我正在尝试计算阈值为 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

在此列表 1 的每个元素都与列表 2 中的每个元素进行比较。我想知道是否有一种方法可以在给定点 (x,y,z) 的情况下最小化比较?

【问题讨论】:

  • 您到底想检测什么?你能给出你的例子的预期答案并解释一下吗?
  • 您对两个列表(每个列表由多个坐标组成)之间的欧几里得距离的确切定义是什么?
  • 我想计算列表 1 的原子与列表 2 之间的欧几里得距离,如果距离小于 4,我需要这些值,但我不希望 list1 的每个元素都与每个元素进行比较在list2 .. 相反,我需要一种降低比较的方法,就像我上面所做的任何预计算一样。这只是一个例子..例如跳过我们知道彼此太接近的值
  • 这仍然没有定义两者之间的欧几里得距离是什么或意味着什么——或者是你试图定义它但不知道如何定义的真正问题?您可以在实现计算结果后的某些内容之后对其进行优化。附言当您回复某人的评论时,请将@their_user_name 放在文本中某处,以便他们收到您已回复的通知。
  • @martineau 我已经编辑了我的问题

标签: python list tuples coordinates


【解决方案1】:

一个有时可以加快速度的预计算是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:]))

【讨论】:

  • 我会自己提议KDtree,但你更快!此外,您的答案确实是一个有充分理由的答案。 +1
  • 这是一个很好的答案 (+1)。我没有导入任何花哨的模块,因为这个问题没有被这样标记。但我想向 OP 展示他们不知道的东西并没有什么坏处。
【解决方案2】:

在 2D 中绘制它以查看它的外观。与原点距离大致相同的点不一定彼此靠近——你有倒过来的三角形不等式。例如,比较点 (0, 10)、(0, 11) 和 (-8, -6)。它们都距原点 10-11 个单位,但最后一个与其他两个相去甚远。

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

【讨论】:

  • 好的,但是在计算欧几里得距离之前我可以做任何类似预计算的方法,这会减少比较,比如将彼此靠近的点组合在一起或沿着这些线进行一些比较
猜你喜欢
  • 2016-06-19
  • 2014-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多