我有以下代码,其中points是多行3列cols列表,coorRadius是我想要找到局部坐标最大值的半径,localCoordinateMaxima是一个数组,我存储这些最大值的i:
for i,x in enumerate(points):
check = 1
for j,y in enumerate(points):
if linalg.norm(x-y) <= coorRadius and x[2] < y[2]:
check = 0
if check == 1:
localCoordinateMaxima.append(i)
print localCoordinateMaxima
不幸的是,当我有几千点时,这需要永远,我正在寻找一种加速它的方法。我尝试用all()条件来做,但是我没有管理它,我甚至不确定它会更有效率。你们能提出一种让它更快的方法吗?
最佳!
答案 0 :(得分:2)
以下是您的代码版本,只是收紧了一点:
for i, x in enumerate(points):
x2 = x[2]
for y in points:
if linalg.norm(x-y) <= coorRadius and x2 < y[2]:
break
else:
localCoordinateMaxima.append(i)
print localCoordinateMaxima
的变化:
x[2]
查询分解出来。答案 1 :(得分:2)
您最好使用KDTree搜索邻居。
from scipy.spatial import cKDTree
tree = cKDTree(points)
pairs = tree.query_pairs(coorRadius)
现在pairs
是一组两个项目元组(i, j)
,其中i < j
和points[i]
以及points[j]
在coorRadius
之内。您现在可以简单地迭代这些,这可能比您当前迭代的len(points)**2
小得多:
is_maximum = [True] * len(points)
for i, j in pairs:
if points[i][2] < points[j][2]:
is_maximum[i] = False
elif points[j][2] < points[i][2]:
is_maximum[j] = False
localCoordinateMaxima, = np.nonzero(is_maximum)
这可以通过矢量化来加速:
pairs = np.array(list(pairs))
pairs = np.vstack((pairs, pairs[:, ::-1]))
pairs = pairs[np.argsort(pairs[:, 0])]
is_z_smaller = points[pairs[:, 0], 2] < points[pairs[:, 1], 2]
bins, = np.nonzero(pairs[:-1, 0] != pairs[1:, 0])
bins = np.concatenate(([0], bins+1))
is_maximum = np.logical_and.reduceat(is_z_smaller, bins)
localCoordinateMaxima, = np.nonzero(is_maximum)
上述代码假设每个点在coorRadius
内至少有一个邻居。如果不是这样,你需要稍微复杂一点:
pairs = np.array(list(pairs))
pairs = np.vstack((pairs, pairs[:, ::-1]))
pairs = pairs[np.argsort(pairs[:, 0])]
is_z_smaller = points[pairs[:, 0], 2] < points[pairs[:, 1], 2]
bins, = np.nonzero(pairs[:-1, 0] != pairs[1:, 0])
has_neighbors = pairs[np.concatenate(([True], bins)), 0]
bins = np.concatenate(([0], bins+1))
is_maximum = np.ones((len(points),), bool)
is_maximum[has_neighbors] &= np.logical_and.reduceat(is_z_smaller, bins)
localCoordinateMaxima, = np.nonzero(is_maximum)
答案 2 :(得分:1)
numpy这不太难。如果需要,可以使用单个(长)表达式执行此操作:
import numpy as np
points = np.array(points)
localCoordinateMaxima = np.where(np.all((np.linalg.norm(points-points[None,:], axis=-1) >
coorRadius) |
(points[:,2] >= points[:,None,2]),
axis=-1))
您当前代码实现的算法基本上是where(not(any(w <= x and y < z)))
。如果你通过其内部的逻辑运算(使用Demorgan的定律)分发not
,你可以通过翻转不等式来避免一级嵌套,获得where(all(w > x or y >= z)))
。
w
是应用于一起广播的点的差异的规范矩阵。 x
是一个常量。 y
和z
都是具有点的第三个坐标的数组,其形状使得它们一起广播为与w
相同的形状。