代码之家  ›  专栏  ›  技术社区  ›  Jason S

在numpy中最简单的方法是索引矩阵的向量,每行不包括一个索引?[副本]

  •  1
  • Jason S  · 技术社区  · 7 年前

    M[0,:] :

    [2, 3.9, 7, 9, 0, 1, 8.1, 3.2]
    

    在运行时,我得到一个整数k,介于0和7之间。我想生成一个向量,该向量包含此行中除k列之外的所有项。(示例:如果k=3,则所需向量为[2,3.9,7,0,1,8.1,3.2])

    如果我有一个索引k的向量,M的每行一个,表示我想从行中排除的列,会怎么样?

    我有点迷路了,除了一个改变结果矩阵的非矢量化循环:

    nrows = M.shape[0]
    result = np.zeros(nrows,M.shape[1]-1))
    for irow in xrange(nrows):
        result[irow,:k[irow]] = M[irow,:k[irow]]   # content before the split point
        result[irow,k[irow]:] = M[irow,k[irow]+1:] # content after the split point
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   Divakar    7 年前

    一种方法是使用 masking / boolean-indexing -

    mask = np.ones(M.shape,dtype=bool)
    mask[np.arange(len(k)),k] = 0
    out = M[mask].reshape(len(M),-1)
    

    或者,我们可以用 broadcasting mask -

    np.not_equal.outer(k,np.arange(M.shape[1]))
    # or k[:,None]!=np.arange(M.shape[1])
    

    因此,给我们一个单行/紧凑型版本-

    out = M[k[:,None]!=np.arange(M.shape[1])].reshape(len(M),-1)
    

    要排除每行多个索引,请编辑第一个方法的高级索引部分-

    def exclude_multiple(M,*klist):
        k = np.stack(klist).T
        mask = np.ones(M.shape,dtype=bool)
        mask[np.arange(len(k))[:,None],k] = 0
        out = M[mask].reshape(len(M),-1)
        return out
    

    In [185]: M = np.arange(40).reshape(4,10)
    
    In [186]: exclude_multiple(M,[1,3,2,0],[4,5,8,1])
    Out[186]: 
    array([[ 0,  2,  3,  5,  6,  7,  8,  9],
           [10, 11, 12, 14, 16, 17, 18, 19],
           [20, 21, 23, 24, 25, 26, 27, 29],
           [32, 33, 34, 35, 36, 37, 38, 39]])
    
        2
  •  1
  •   Jason S    7 年前

    改进@Divakar的答案,将其扩展到每行零个或多个排除索引:

    def excluding(A, *klist):
        """ 
        excludes column k from each row of A, for each k in klist 
        (make sure the index vectors have no common elements)
        """
        mask = np.ones(A.shape,dtype=bool)
        for k in klist:
            mask[np.arange(len(k)),k] = 0
        return A[mask].reshape(len(A),-1)
    

    测试:

    M = np.arange(40).reshape(4,10)
    excluding(M,[1,3,2,0],[4,5,8,1])
    

    返回

    array([[ 0,  2,  3,  5,  6,  7,  8,  9],
           [10, 11, 12, 14, 16, 17, 18, 19],
           [20, 21, 23, 24, 25, 26, 27, 29],
           [32, 33, 34, 35, 36, 37, 38, 39]])