Fre*_*den 5 python sorting floating-point numpy
我有一个N
三维点的集合.这些存储为np.array
具有的形状(N,3)
.所有点都是不同的,任何两点之间的最小距离~1e-5
.我正在寻找一种获得迭代这些点的顺序的方法,这些顺序既与它们当前的顺序无关,np.array
又与单个组件的小扰动无关.
满足第一个要求的最简单方法是np.lexsort
使用
np.lexsort(my_array.T)
Run Code Online (Sandbox Code Playgroud)
但是在健壮性部门失败了:
In [6]: my_array = np.array([[-0.5, 0, 2**0.5], [0.5, 0, 2**0.5 - 1e-15]])
In [7]: my_array[np.lexsort(my_array.T)]
Out[7]:
array([[ 0.5 , 0. , 1.41421356],
[-0.5 , 0. , 1.41421356]])
Run Code Online (Sandbox Code Playgroud)
我们可以看到,在这种情况下,排序对扰动非常敏感.因此,我正在寻找一个模糊变量,np.lexsort
如果一个轴中的两个值在公差范围内,它将移动到下一个轴epsilon
.(或任何可以让我获得订购的替代机制.)
由于我的应用程序有数百万个这些集合,所有这些都需要订购,性能是一个值得关注的问题(这就是为什么我没有盲目地试图推出我自己的容忍np.lexsort而没有先看到是否有更好的方法来做它).
我最终的解决方案是:
def fuzzysort(arr, idx, dim=0, tol=1e-6):
# Extract our dimension and argsort
arrd = arr[dim]
srtdidx = sorted(idx, key=arrd.__getitem__)
i, ix = 0, srtdidx[0]
for j, jx in enumerate(srtdidx[1:], start=1):
if arrd[jx] - arrd[ix] >= tol:
if j - i > 1:
srtdidx[i:j] = fuzzysort(arr, srtdidx[i:j], dim + 1, tol)
i, ix = j, jx
if i != j:
srtdidx[i:] = fuzzysort(arr, srtdidx[i:], dim + 1, tol)
return srtdidx
Run Code Online (Sandbox Code Playgroud)
我注意到,对于上述问题,这有点过度设计。与np.lexsort
数组一样,必须以转置形式传递。该idx
参数允许控制考虑哪些索引(允许粗略地屏蔽元素)。否则list(xrange(0, N))
就可以了。
性能不太好。然而,这主要是 NumPy 标量类型表现不佳的结果。预先调用tolist()
数组可以在一定程度上改善这种情况。