Numpy 在一个数组中查找那些为;“关闭”;

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],

我有一个一维排序数组,希望找到所有元素对,它们的差值不大于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],
       [ 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