【问题标题】:Get NumPy Array Indices in Array B for Unique Values in Array A, for Values Present in Both Arrays, Aligned with Array A获取数组 B 中的 NumPy 数组索引以获取数组 A 中的唯一值、两个数组中都存在的值、与数组 A 对齐
【发布时间】:2013-07-10 09:45:12
【问题描述】:

我有两个 NumPy 数组:

A = asarray(['4', '4', '2', '8', '8', '8', '8', '8', '16', '32', '16', '16', '32'])
B = asarray(['2', '4', '8', '16', '32'])

我想要一个函数,它以A, B 作为参数,并尽可能高效地返回A 中每个值的B 中的索引,与A 对齐。

这些是上述测试用例的输出:

indices = [1, 1, 0, 2, 2, 2, 2, 2, 3, 4, 3, 3, 4]

我尝试探索in1d()where()nonzero(),但没有成功。非常感谢任何帮助。

编辑:数组是字符串。

【问题讨论】:

    标签: python arrays numpy scipy


    【解决方案1】:

    你也可以这样做:

    >>> np.digitize(A,B)-1
    array([1, 1, 0, 2, 2, 2, 2, 2, 3, 4, 3, 3, 4])
    

    根据文档,您应该能够指定 right=False 并跳过减一部分。这对我不起作用,可能是由于版本问题,因为我没有 numpy 1.7。

    我不确定你在做什么,但一个简单且非常快速的方法是:

    >>> A = np.asarray(['4', '4', '2', '8', '8', '8', '8', '8', '16', '32', '16', '16', '32'])
    >>> B,indices=np.unique(A,return_inverse=True)
    >>> B
    array(['16', '2', '32', '4', '8'],
          dtype='|S2')
    >>> indices
    array([3, 3, 1, 4, 4, 4, 4, 4, 0, 2, 0, 0, 2])
    
    >>> B[indices]
    array(['4', '4', '2', '8', '8', '8', '8', '8', '16', '32', '16', '16', '32'],
          dtype='|S2')
    

    顺序会有所不同,但如果需要可以更改。

    【讨论】:

    • 你隐含地依赖 B 被排序。
    • 但除此之外,这很容易解决,例如正如我的回答,这比np.searchsorted 快,所以+1。
    • 让我说 A 和 B 是字符串数组,让事情变得更复杂:( 显然 digitize() 不喜欢。
    【解决方案2】:

    对于此类事情,尽快在B 中进行查找非常重要。字典提供O(1) 查找时间。所以,首先,让我们构造这个字典:

    >>> indices = dict((value,index) for index,value in enumerate(B))
    >>> indices
    {8: 2, 16: 3, 2: 0, 4: 1, 32: 4}
    

    然后只需遍历A 并找到对应的索引:

    >>> [indices[item] for item in A]
    [1, 1, 0, 2, 2, 2, 2, 2, 3, 4, 3, 3, 4]
    

    【讨论】:

    • 谢谢,太好了。但是,有没有办法在 NumPy-C-happy-land 中做到这一点?如果我们采用这条路线,{dict: comprehension} 似乎也会更快一些。有没有很好的 NumPy 方法来做到这一点而不必传递一个 dict?
    • @Will 如果B 很大,那么让O(1) 查找复杂性很重要。我对numpy 不熟悉,但敷衍的搜索并没有在numpy 中产生对dict 类似物的任何引用。如果B 很小,那么在 numpy 中执行所有操作可能会更快。如果是这样,请等待另一个答案,也许有人能够提出全能的解决方案。
    【解决方案3】:

    我认为你可以使用np.searchsorted

    >>> A = asarray([4, 4, 2, 8, 8, 8, 8, 8, 16, 32, 16, 16, 32])
    >>> B = asarray([2, 8, 4, 32, 16])
    >>> sort_b = np.argsort(B)
    >>> idx_of_a_in_sorted_b = np.searchsorted(B, A, sorter=sort_b)
    >>> idx_of_a_in_b = np.take(sort_b, idx_of_a_in_sorted_b)
    >>> idx_of_a_in_b
    array([2, 2, 0, 1, 1, 1, 1, 1, 4, 3, 4, 4, 3], dtype=int64)
    

    请注意,B 是从您的版本中打乱的,因此输出不同。如果A 中的某些项目不在B 中(您可以使用np.all(np.in1d(A, B)) 检查),那么这些值的返回索引将是废话,您甚至可能从最后一行得到IndexError(如果B 中缺少A 中的最大值)。

    【讨论】:

      【解决方案4】:

      numpy_indexed 包(免责声明:我是它的作者)实现了与 Jaime 的解决方案相同的解决方案;但具有良好的界面、测试和许多相关的有用功能:

      import numpy_indexed as npi
      print(npi.indices(B, A))
      

      【讨论】:

      • 您不断发布几乎相同的答案,指向您的实用程序,但不清楚您与链接存储库的从属关系。为了防止它们被标记为垃圾邮件,您应该采取以下步骤:How can I link to an external resource in a community-friendly way?
      • 感谢您的提醒,但您确定这些关联条件适用吗?这不是我要链接的“产品或网站”,而是一个开源项目。在这种情况下提及我的作者身份感觉更像是自我推销,而不是有用的信息。
      • 基于类似的反馈,我决定添加免责声明;再次感谢。
      【解决方案5】:

      我不确定这有多有效,但它确实有效:

      import numpy as np
      A = np.asarray(['4', '4', '2', '8', '8', '8', '8', '8', '16', '32', '16', '16', '32'])
      B = np.asarray(['2', '4', '8', '16', '32'])
      idx_of_a_in_b=np.argmax(A[np.newaxis,:]==B[:,np.newaxis],axis=0)
      print(idx_of_a_in_b)
      

      我从中得到:

      [1 1 0 2 2 2 2 2 3 4 3 3 4]
      

      【讨论】:

      • 这似乎是一个!谢谢!
      • 注意:这个解在输入端是二次方的,并不理想。
      猜你喜欢
      • 2018-05-09
      • 1970-01-01
      • 2018-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-28
      相关资源
      最近更新 更多