Numpy 在一个数组中查找那些为;“关闭”;
我有一个一维排序数组,希望找到所有元素对,它们的差值不大于5 一种天真的方法是做N^2比较Numpy 在一个数组中查找那些为;“关闭”;,numpy,Numpy,我有一个一维排序数组,希望找到所有元素对,它们的差值不大于5 一种天真的方法是做N^2比较 diffs = np.tile(x, (x.size,1) ) - x[:, np.newaxis] D = np.logical_and(diffs>0, diffs<5) indicies = np.argwhere(D) 结果应该是这样的 array([[ 0, 1], [ 3, 4], [ 5, 6], [ 5, 7],
diffs = np.tile(x, (x.size,1) ) - x[:, np.newaxis]
D = np.logical_and(diffs>0, diffs<5)
indicies = np.argwhere(D)
结果应该是这样的
array([[ 0, 1],
[ 3, 4],
[ 5, 6],
[ 5, 7],
[ 6, 7],
[ 9, 10]], dtype=int64)
您对阵列进行切片的想法是一种非常有效的方法。由于您的数据已排序,您只需计算差异并将其拆分:
d=np.diff(x)
ind=np.where(d>5)[0]
pieces=np.split(x,ind)
这里的parties
是一个列表,您可以在每个元素上使用自己的代码进行循环
最好的算法在很大程度上取决于我不知道的数据的性质。例如,另一种可能是编写嵌套循环:
pairs=[]
for i in range(x.size):
j=i+1
while x[j]-x[i]<=5 and j<x.size:
pairs.append([i,j])
j+=1
pairs=[]
对于范围内的i(x.size):
j=i+1
当x[j]-x[i]时,这里有一个解决方案,它迭代偏移量,同时收缩候选集,直到没有剩余:
import numpy as np
def f_pp(A, maxgap):
d0 = np.diff(A)
d = d0.copy()
IDX = []
k = 1
idx, = np.where(d <= maxgap)
vidx = idx[d[idx] > 0]
while vidx.size:
IDX.append(vidx[:, None] + (0, k))
if idx[-1] + k + 1 == A.size:
idx = idx[:-1]
d[idx] = d[idx] + d0[idx+k]
k += 1
idx = idx[d[idx] <= maxgap]
vidx = idx[d[idx] > 0]
return np.concatenate(IDX, axis=0)
data = np.cumsum(np.random.exponential(size=10000)).repeat(np.random.randint(1, 20, (10000,)))
pairs = f_pp(data, 1)
#pairs = set(map(tuple, pairs))
from timeit import timeit
kwds = dict(globals=globals(), number=100)
print(data.size, 'points', pairs.shape[0], 'close pairs')
print('pp', timeit("f_pp(data, 1)", **kwds)*10, 'ms')
你可以有两个索引-左和右。左边负责较小的元素,右边负责较大的元素。因此,一旦您找到当前左侧的所有有效权限,就可以增加左侧并继续使用右侧。这是一种O(n)方法,你可以这样做,因为数组已排序。@user1055395它不能是O(n)且同时正确,因为如果所有元素都接近,那么仅枚举所有对就已经是O(n^2)@PaulPanzer在我添加注释时,我认为不允许重复。在我得知它们是允许的之后,我同意O(N^2)是这里最坏的情况。由于问题的性质,我知道有很多间隙大于5,所以虽然O(N^2)是最坏的情况,但我希望它会比这快得多。你能提供一个数据示例吗?
import numpy as np
def f_pp(A, maxgap):
d0 = np.diff(A)
d = d0.copy()
IDX = []
k = 1
idx, = np.where(d <= maxgap)
vidx = idx[d[idx] > 0]
while vidx.size:
IDX.append(vidx[:, None] + (0, k))
if idx[-1] + k + 1 == A.size:
idx = idx[:-1]
d[idx] = d[idx] + d0[idx+k]
k += 1
idx = idx[d[idx] <= maxgap]
vidx = idx[d[idx] > 0]
return np.concatenate(IDX, axis=0)
data = np.cumsum(np.random.exponential(size=10000)).repeat(np.random.randint(1, 20, (10000,)))
pairs = f_pp(data, 1)
#pairs = set(map(tuple, pairs))
from timeit import timeit
kwds = dict(globals=globals(), number=100)
print(data.size, 'points', pairs.shape[0], 'close pairs')
print('pp', timeit("f_pp(data, 1)", **kwds)*10, 'ms')
99963 points 1020651 close pairs
pp 43.00256529124454 ms