【问题标题】:Indexing one array by another in numpy在numpy中用另一个数组索引一个数组
【发布时间】:2020-06-11 17:29:51
【问题描述】:

假设我有一个矩阵 A 有一些任意值:

array([[ 2, 4, 5, 3],
       [ 1, 6, 8, 9],
       [ 8, 7, 0, 2]])

还有一个矩阵B,其中包含A中元素的索引:

array([[0, 0, 1, 2],
       [0, 3, 2, 1],
       [3, 2, 1, 0]])

如何从B指向的A中选择值,即:

A[B] = [[2, 2, 4, 5],
        [1, 9, 8, 6],
        [2, 0, 7, 8]]

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    最近的版本添加了一个 take_along_axis 函数来完成这项工作:

    A = np.array([[ 2, 4, 5, 3], 
                  [ 1, 6, 8, 9], 
                  [ 8, 7, 0, 2]])  
                                              
    B = np.array([[0, 0, 1, 2], 
                  [0, 3, 2, 1], 
                  [3, 2, 1, 0]])     
                                            
    np.take_along_axis(A, B, 1)  
                                           
    Out[]: 
    array([[2, 2, 4, 5],
           [1, 9, 8, 6],
           [2, 0, 7, 8]])
    

    还有一个put_along_axis

    【讨论】:

      【解决方案2】:

      编辑:np.take_along_axis 是自 numpy 1.15 以来实现的此用例的内置函数。请参阅下面@hpaulj 的answer 了解如何使用它。


      你可以使用NumPy's advanced indexing -

      A[np.arange(A.shape[0])[:,None],B]
      

      也可以使用linear indexing -

      m,n = A.shape
      out = np.take(A,B + n*np.arange(m)[:,None])
      

      示例运行 -

      In [40]: A
      Out[40]: 
      array([[2, 4, 5, 3],
             [1, 6, 8, 9],
             [8, 7, 0, 2]])
      
      In [41]: B
      Out[41]: 
      array([[0, 0, 1, 2],
             [0, 3, 2, 1],
             [3, 2, 1, 0]])
      
      In [42]: A[np.arange(A.shape[0])[:,None],B]
      Out[42]: 
      array([[2, 2, 4, 5],
             [1, 9, 8, 6],
             [2, 0, 7, 8]])
      
      In [43]: m,n = A.shape
      
      In [44]: np.take(A,B + n*np.arange(m)[:,None])
      Out[44]: 
      array([[2, 2, 4, 5],
             [1, 9, 8, 6],
             [2, 0, 7, 8]])
      

      【讨论】:

      • 我不明白这些是如何工作的......你能补充一些解释吗?
      • @JasonS 基本上使用沿第一个轴的范围数组为B 中的每个元素沿该轴选择一个。提供的链接应提供所需的所有详细信息。
      • 嗯...好吧,这很好,但我查看了高级索引链接,这对我来说没有意义。我需要将您的示例扩展到仅应用最后一个索引的 N 维数组,我不知道该怎么做。
      【解决方案3】:

      我知道这是一个老问题,但使用索引的另一种方法是:

      A[np.indices(B.shape)[0], B]
      

      输出:

      [[2 2 4 5]
       [1 9 8 6]
       [2 0 7 8]]
      

      【讨论】:

      • 非常优雅的做法!
      【解决方案4】:

      以下是使用for循环的解决方案:

      outlist = []
      for i in range(len(B)):
          lst = []    
          for j in range(len(B[i])):
              lst.append(A[i][B[i][j]])
          outlist.append(lst)
      outarray = np.asarray(outlist)
      print(outarray)
      

      上面也可以写成更简洁的列表理解形式:

      outlist = [ [A[i][B[i][j]] for j in range(len(B[i]))]
                      for i in range(len(B))  ]
      outarray = np.asarray(outlist)
      print(outarray)
      

      输出:

      [[2 2 4 5]
       [1 9 8 6]
       [2 0 7 8]]
      

      【讨论】:

      • 提问者正在寻找一种使用简单切片而不是 for 循环的解决方案。切片比 for 循环快得多。
      猜你喜欢
      • 2016-03-09
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 1970-01-01
      相关资源
      最近更新 更多