3

我需要数组元素之间的最小距离。

我做了:

numpy.min(numpy.ediff1d(numpy.sort(x)))

有没有更好/更高效/更优雅/更快的方法来做到这一点?

4

3 回答 3

4

如果您追求绝对速度,这里有一些时间安排:

In [13]: a = np.random.rand(1000)

In [14]: %timeit np.sort(a)
10000 loops, best of 3: 31.9 us per loop

In [15]: %timeit np.ediff1d(a)
100000 loops, best of 3: 15.2 us per loop

In [16]: %timeit np.diff(a)
100000 loops, best of 3: 7.76 us per loop

In [17]: %timeit np.min(a)
100000 loops, best of 3: 3.19 us per loop

In [18]: %timeit np.unique(a)
10000 loops, best of 3: 53.8 us per loop

的时间unique是希望它与 相当快,并且如果唯一数组的长度比数组本身短(因为这意味着你的答案是)sort,你可以在没有调用的情况下提前爆发。但是,开销大于任何收益。diffmin0unique

所以看来我能提供的唯一潜在改进是替换ediff1ddiff

In [19]: %timeit np.min(np.diff(np.sort(a)))
10000 loops, best of 3: 47.7 us per loop

In [20]: %timeit np.min(np.ediff1d(np.sort(a)))
10000 loops, best of 3: 57.1 us per loop
于 2013-04-11T17:18:20.330 回答
2

您当前的方法绝对是最佳的。通过首先排序,您可以减少每个元素之间的空间,ediff1d并将返回一个差异数组。这里有一个建议:

因为我们知道差值必须是正的,因为我们有一个升序排序,所以我们可以ediff1d手动实现并在差值为零的地方包含一个中断。这样,如果你有排序数组x

[1, 1, 2, 3, 4, 5, 6, 7, ... , n]

您的函数不是通过 n 个元素,而是ediff1d提前中断并仅覆盖前两个元素,返回[0]. min这也减少了差异数组的大小,减少了调用所需的迭代量。

这是一个不使用 numpy 的示例:

x = [1, 12, 3, 8, 4, 1, 4, 9, 1, 29, 210, 313, 12]

def ediff1d_custom(x):
    darr = []

    for i in xrange(len(x)):
        if i != len(x) - 1:
            diff = x[i + 1] - x[i]
            darr.append(diff)

            if diff == 0:
                break

    return darr

print min(ediff1d_custom(sorted(x))) # prints 0
于 2013-04-11T16:26:07.780 回答
0
try:
    min(x[i+1]-x[i] for i in xrange(0, len(x)-1))
except ValueError:
    print 'Array contains less than two values.'
于 2013-04-11T17:08:14.083 回答