【问题标题】:numpy search array for multiple values, and returns their indicesnumpy 搜索多个值的数组,并返回它们的索引
【发布时间】:2015-08-21 11:14:39
【问题描述】:

如何在 numpy 数组中搜索一小组值(未排序,不应更改)? 它应该返回这些值的索引。

例如:

a = np.array(['d', 'v', 'h', 'r', 'm', 'a'])   # in general it will be large
query = np.array(['a', 'v', 'd'])

# Required:
idnx = someNumpyFunction(a, query)

print(indx)       # should be [5, 1, 0]

我是 numpy 的初学者,我找不到同时为多个值执行此任务的正确方法(我知道 np.where(a=='d') 可以为单个值执行此操作值搜索)。

【问题讨论】:

  • 如果query 很小,并且没有严格的优化需求,我建议使用简单的for i in query: np.where(a==i)。你当然要处理边缘情况:没有匹配,不止一个匹配。
  • 如果在a 中找不到query 元素,你想要什么?重复呢?
  • 在我的情况下,查询元素是唯一的并且始终存在。但即使有一个解决方案可能返回 -1 或 outOfIndex 未找到它也没关系,但不会引发异常

标签: arrays python-3.x search numpy


【解决方案1】:

检查一个数组与另一个数组的经典方法是调整形状并使用'==':

In [250]: arr==query[:,None]
Out[250]: 
array([[False, False, False, False, False,  True],
       [False,  True, False, False, False, False],
       [ True, False, False, False, False, False]], dtype=bool)

In [251]: np.where(arr==query[:,None])
Out[251]: (array([0, 1, 2]), array([5, 1, 0]))

如果在a 中找不到元素query,则它的“行”将丢失,例如[0,2] 而不是 [0,1,2]

In [261]: np.where(arr==np.array(['a','x','v'],dtype='S')[:,None])
Out[261]: (array([0, 2]), array([5, 1]))   

对于这个小例子,它比等效的列表理解要快得多:

np.hstack([(arr==i).nonzero()[0] for i in query])

它比searchsorted 解决方案慢一点。 (在该解决方案中,如果未找到 query 元素,则 i 超出范围)。


Stefano 建议fromiter。与列表的hstack 相比,它节省了一些时间:

In [313]: timeit np.hstack([(arr==i).nonzero()[0] for i in query])10000 loops, best of 3: 49.5 us per loop

In [314]: timeit np.fromiter(((arr==i).nonzero()[0] for i in query), dtype=int, count=len(query))
10000 loops, best of 3: 35.3 us per loop

但是如果引发错误是缺少元素,或者有多次出现。 hstack 可以处理可变长度条目,fromiter 不能。

np.flatnonzero(arr==i)().nonzero()[0] 慢,但我还没有研究原因。

【讨论】:

  • +1 用于转置query 并利用广播的技术。内存占用为n*k 字节(dtype=bool 的大小),对于小的k,它与nn 字节相当。
  • 写循环版本更高效的方法是np.fromiter((np.flatnonzero(arr==i) for i in query), dtype=int, count=len(query))
【解决方案2】:

您可以在排序后的数组上使用np.searchsorted,然后将返回的索引恢复为原始数组。为此,您可以使用np.argsort;如:

>>> indx = a.argsort()  # indices that would sort the array
>>> i = np.searchsorted(a[indx], query)  # indices in the sorted array
>>> indx[i]  # indices with respect to the original array
array([5, 1, 0])

如果a 的大小为nquery 的大小为k,这将是O(n log n + k log n),如果log n < k 进行线性搜索,这将比O(n k) 快。

【讨论】:

  • 其实在'n'很大k很小的情况下,k被认为是一个常数,这个解可以减少到'O(n log n)',而不是'O(n) ' 用于搜索未排序的数组。但是我们可以说,如果我在一个循环中进行多次搜索或其他什么,这个解决方案通常是合适的,在这种情况下,我可以保存变量 indx 并且不必再次排序.
  • 如果没有其他简单的方法,我会接受这个解决方案。在 R 和 Matlab 中是不是很容易,就像索引一样!!
  • 这个解决方案的内存占用是n*(a.itemsize + indx.itemsize),因为a[indx]是一个副本而不是一个视图。我不清楚在哪种假设下这会比在query的元素上进行简单循环更快
  • 是的,循环是一种解决方案,但我希望能有一个像 R 和 Matlab 那样简单的解决方案。
猜你喜欢
  • 2013-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-15
  • 2010-11-13
  • 2013-06-04
  • 2019-01-15
  • 2012-01-15
相关资源
最近更新 更多