【问题标题】:Optimal way for finding index of 'greatest value less than' in Numpy array在 Numpy 数组中查找“最大值小于”索引的最佳方法
【发布时间】:2016-12-09 01:32:50
【问题描述】:

我有一个排序的 numpy 数组 X 以及两个常量 kdelta,它们不在 X 中。我想找到对应的索引,X 中的最大值小于或等于k,并且该值必须在deltadelta 之内,即我想要

max {i | k - delta <= X[i] <= k }    (1)

注意这个集合可能是空的,在这种情况下我会返回None。我目前认为我这样做的方式并不理想,因为它没有利用在第一步订购 X 的事实

# Get the max from the set of indices in X satisfying (1)
idx = np.where((k-delta <= X) * (X <= k))[0].max()

我不确定 Numpy 在执行此操作时有多聪明,因为它还不知道 X 已排序,因此我认为 (k-delta &lt;= X) * (X &lt;= k)) 将花费比必要时间更长的时间。请注意,我们可以使用.max(),因为我们知道数组已排序。

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

【问题讨论】:

  • 你说数组是排序的。那么满足你条件的元素不是总是在索引中k之前的吗?这一事实大大简化了解决方案。
  • 是的,但是k 不在X 中,所以我必须先比较k 和元素n X
  • 我明白了。需要注意的是k 不一定在X 中。你可能想在你的问题中澄清它。

标签: python arrays performance sorting numpy


【解决方案1】:

利用排序顺序的一种有效方法是使用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

【讨论】:

  • 我喜欢这个,请注意,要准确回答问题,函数应该返回right_idx,而不是X[right_idx]。我会等着看有没有人在接受之前有任何速度分析。
  • @rwolst 相应地更新了我的帖子。在那里添加了一些时间。
【解决方案2】:

Numpy.argmax 可能有助于利用排序列表。

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

【讨论】:

  • 请注意,如果有关系,np.argmax 将返回第一个最大值的索引,但更喜欢最后一个似乎更合乎逻辑,我也不认为 np.argmax 会利用的排序列表
猜你喜欢
  • 1970-01-01
  • 2018-07-27
  • 2016-03-17
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多