用于收集numpy数组的高效查找表

时间:2015-08-19 12:53:55

标签: python numpy hashmap binary-tree lookup

我想知道在Python中为浮点数(以及浮点数集合)创建查找表的最有效方法是什么。由于两个组和dicts都需要键可以清洗,我猜不能使用某种接近来检查已经插入的接近度,是吗?我看过this answer并不是我想要的,因为我不想给用户创造正确密钥的负担,而且我需要扩展它用于花车的集合。 例如,给出以下代码:

>>> import numpy as np
>>> a = {np.array([0.01, 0.005]): 1}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'numpy.ndarray'
>>> a = {tuple(np.array([0.01, 0.005])): 1}
>>> tuple(np.array([0.0100000000000001,0.0050002])) in a
False

我希望最后一句话返回True。来自C ++世界,我将创建一个std::map并提供一个比较函数,该函数可以与某些用户定义的容差进行比较,以检查这些值是否已添加到数据结构中。当然,这个问题自然会扩展到数组的查找表(例如numpy数组)。那么,什么是实现我所寻找的最有效的方式?

1 个答案:

答案 0 :(得分:1)

由于您对3D点感兴趣,因此您可以考虑使用一些针对存储空间数据进行优化的数据结构,例如KD-tree。这是Scipy中的available,允许查找最接近给定坐标的点。在您查看了这一点之后,您可以检查一下您是否在接受新点的容忍范围内。

用法应该是这样的(未经测试,我自己从未使用过):

from scipy.spatial import KDTree
points = ... # points is [Nx3]
tree = KDTree(points)  
new_point = ... # array of length 3
distance, nearest_index = tree.query(new_point)
if distance > tolerance:  # add point
    points = np.vstack((points, new_point))
    tree = KDTree(points)  # generate tree from scratch

请注意,KD树在查找静态点集合中的点是有效的(查找成本为O(log(N)),但它们未针对重复添加新点进行优化.Scipy实现甚至缺乏添加新点的方法,因此每次插入新点时都必须生成一个新树。由于此操作可能是O(N*log(N)),因此对所有距离进行强力计算可能更快,费用为O(N)。请注意,还有一个替代版本cKDTree,可能在C中实现了速度,文档在这方面并不是很清楚。