【问题标题】:Indexing NumPy 2D array with another 2D array用另一个二维数组索引 NumPy 二维数组
【发布时间】:2012-04-10 17:56:46
【问题描述】:

我有类似的东西

m = array([[1, 2],
            [4, 5],
            [7, 8],
            [6, 2]])

select = array([0,1,0,0])

我的目标是

result = array([1, 5, 7, 6])

我在Simplfy row AND column extraction, numpy 阅读时尝试了_ix,但这并没有达到我想要的结果。

附言如果您能想到更准确的问题,请更改此问题的标题。

【问题讨论】:

  • 我建议将“按列表过滤二维数组”作为标题。

标签: python numpy indexing scipy


【解决方案1】:

由于标题是指用另一个 2D 数组索引一个 2D 数组,因此可以找到实际的通用 numpy 解决方案here

简而言之: 形状为 (n,m) 的二维索引数组具有任意大尺寸 m,名为 inds,用于访问另一个形状为 (n,k) 的二维数组的元素,名为 @987654323 @:

# array of index offsets to be added to each row of inds
offset = np.arange(0, inds.size, inds.shape[1])

# numpy.take(B, C) "flattens" arrays B and C and selects elements from B based on indices in C
Result = np.take(B, offset[:,np.newaxis]+inds)

另一种不使用np.take,我觉得更直观的解决方案如下:

B[np.expand_dims(np.arange(B.shape[0]), -1), inds]

这种语法的优点是它既可以用于基于inds(如np.take)从B读取元素,也可以用于赋值。

【讨论】:

    【解决方案2】:

    恕我直言,这是最简单的变体:

    m[np.arange(4), select]
    

    【讨论】:

      【解决方案3】:

      numpy 方法是使用np.choose 或花哨的索引/获取(见下文):

      m = array([[1, 2],
                 [4, 5],
                 [7, 8],
                 [6, 2]])
      select = array([0,1,0,0])
      
      result = np.choose(select, m.T)
      

      因此,不需要 python 循环或任何东西,因为 numpy 为您提供了所有速度优势。 m.T 只是需要,因为选择实际上更多是两个数组 np.choose(select, (m[:,0], m[:1])) 之间的选择,但像这样使用它很直接。


      使用精美的索引

      result = m[np.arange(len(select)), select]
      

      如果速度非常重要np.take,它适用于一维视图(出于某种原因,它的速度要快一些,但可能不适用于这些小阵列):

      result = m.take(select+np.arange(0, len(select) * m.shape[1], m.shape[1]))
      

      【讨论】:

      • 在撰写本文时 (np 1.9.2),np.choose() 可能有最多 32 个元素的严重限制。如果 m 的较长维度超过此值,那么我会收到“ValueError: Need between 2 and (32) array objects (inclusive)”。
      【解决方案4】:

      我更喜欢使用 NP.where 来执行此类索引任务(而不是 NP.ix_

      OP 中没有提到的是结果是按位置(源数组中的行/列)还是按某些条件(例如,m >= 5)选择的。无论如何,下面的代码 sn-p 涵盖了这两种情况。

      三个步骤:

      1. 创建条件数组

      2. 通过调用 NP.where 生成一个索引数组,传入这个 条件数组;和

      3. 对源数组应用这个索引数组


      >>> import numpy as NP
      
      >>> cnd = (m==1) | (m==5) | (m==7) | (m==6)
      >>> cnd
        matrix([[ True, False],
                [False,  True],
                [ True, False],
                [ True, False]], dtype=bool)
      
      >>> # generate the index array/matrix 
      >>> # by calling NP.where, passing in the condition (cnd)
      >>> ndx = NP.where(cnd)
      >>> ndx
        (matrix([[0, 1, 2, 3]]), matrix([[0, 1, 0, 0]]))
      
      >>> # now apply it against the source array   
      >>> m[ndx]
        matrix([[1, 5, 7, 6]])
      


      传递给 NP.where 的参数 cnd 是一个布尔数组,在这种情况下,它是由复合条件表达式组成的单个表达式的结果(上面的第一行)

      如果构造这样的值过滤器不适用于您的特定用例,那很好,您只需要生成实际的布尔矩阵(cnd 的值) 其他方式(或直接创建)。

      【讨论】:

        【解决方案5】:
        result = array([m[j][0] if i==0 else m[j][1] for i,j in zip(select, range(0, len(m)))])
        

        【讨论】:

          【解决方案6】:

          用python怎么样?

          result = array([subarray[index] for subarray, index in zip(m, select)])
          

          【讨论】:

            猜你喜欢
            • 2021-06-04
            • 1970-01-01
            • 1970-01-01
            • 2020-07-30
            • 2021-03-03
            • 2019-07-28
            • 1970-01-01
            • 2011-07-07
            • 1970-01-01
            相关资源
            最近更新 更多