找到Numpy数组中“最大值小于”的索引的最佳方法

时间:2016-08-03 11:00:53

标签: python arrays performance sorting numpy

我有一个排序的numpy数组X以及两个常量kdelta不在X中。我想找到对应的索引,X中的最大值小于或等于k,且值必须在delta的{​​{1}}范围内,即我想要< / p>

k

请注意,此集可能为空,在这种情况下,我将返回max {i | k - delta <= X[i] <= k } (1) 。我这样做的方式我目前感觉不够优秀,因为它没有利用None在第一步中订购的事实

X

我不确定Numpy在执行此操作时有多聪明,因为它还不知道# Get the max from the set of indices in X satisfying (1) idx = np.where((k-delta <= X) * (X <= k))[0].max() 已经排序,因此我认为X需要的时间超过必要时间。请注意,我们可以使用(k-delta <= X) * (X <= k)),因为我们知道数组已经排序。

这样做的最佳方式是什么?

2 个答案:

答案 0 :(得分:2)

利用排序顺序的一种有效方法是使用np.searchsorted -

def largest_within_delta(X, k, delta):
    right_idx = X.searchsorted(k,'right')-1
    if (k - X[right_idx]) <= delta:
        return right_idx
    else:
        return None

示例运行以涵盖各种情况 -

In [216]: X
Out[216]: array([ 8,  9, 33, 35, 36, 37, 44, 45, 71, 81])

In [217]: largest_within_delta(X, 36, 0) # this k is already in array
Out[217]: 4

In [218]: largest_within_delta(X, 36, 1) # shouldn't choose for next one 37
Out[218]: 4    

In [220]: largest_within_delta(X, 40, 3) # Gets 37's index
Out[220]: 5

In [221]: largest_within_delta(X, 40, 2) # Out of 37's reach

运行时测试

In [212]: # Inputs
     ...: X = np.unique(np.random.randint(0,1000000,(10000)))
     ...: k = 50000
     ...: delta = 100
     ...: 

In [213]: %timeit np.where((k-delta <= X) * (X <= k))[0].max()
10000 loops, best of 3: 44.6 µs per loop

In [214]: %timeit largest_within_delta(X, k, delta)
100000 loops, best of 3: 3.22 µs per loop

答案 1 :(得分:1)

Numpy.argmax可以用于利用排序列表。

import numpy as np
np.argmax(X <= k) if k-d < np.argmax(X <= k) < k+d else None