【问题标题】:How can I remove a column from a sparse matrix efficiently?如何有效地从稀疏矩阵中删除一列?
【发布时间】:2011-01-23 00:53:02
【问题描述】:

如果我使用 sparse.lil_matrix 格式,如何轻松有效地从矩阵中删除一列?

【问题讨论】:

    标签: python matrix numpy scipy algebra


    【解决方案1】:

    更简单、更快捷。您甚至可能不需要转换为 csr,但我只是确定它可以与 csr 稀疏矩阵一起使用,并且之间的转换应该不是问题。

    from scipy import sparse
    
    x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list])
    

    【讨论】:

    • 为什么要使用 CSR(压缩稀疏行)矩阵进行列切片? CSR 格式的缺点之一是“慢列切片操作(考虑 CSC)”(根据 scipy 文档)。您可能应该改用csc_matrix 转换。
    【解决方案2】:

    我自己也一直想要这个,实际上还没有一个很好的内置方法可以做到这一点。这是一种方法。我选择创建一个 lil_matrix 的子类并添加 remove_col 函数。如果需要,您可以改为将 removecol 函数添加到 lib/site-packages/scipy/sparse/lil.py 文件中的 lil_matrix 类。代码如下:

    from scipy import sparse
    from bisect import bisect_left
    
    class lil2(sparse.lil_matrix):
        def removecol(self,j):
            if j < 0:
                j += self.shape[1]
    
            if j < 0 or j >= self.shape[1]:
                raise IndexError('column index out of bounds')
    
            rows = self.rows
            data = self.data
            for i in xrange(self.shape[0]):
                pos = bisect_left(rows[i], j)
                if pos == len(rows[i]):
                    continue
                elif rows[i][pos] == j:
                    rows[i].pop(pos)
                    data[i].pop(pos)
                    if pos == len(rows[i]):
                        continue
                for pos2 in xrange(pos,len(rows[i])):
                    rows[i][pos2] -= 1
    
            self._shape = (self._shape[0],self._shape[1]-1)
    

    我已经尝试过了,没有发现任何错误。我当然认为这比将列切出要好,据我所知,这只会创建一个新矩阵。

    我也决定做一个 removerow 函数,但我认为它不如 removecol 好。我无法以我想要的方式从 ndarray 中删除一行。这是可以添加到上述类中的 removerow

        def removerow(self,i):
            if i < 0:
                i += self.shape[0]
    
            if i < 0 or i >= self.shape[0]:
                raise IndexError('row index out of bounds')
    
            self.rows = numpy.delete(self.rows,i,0)
            self.data = numpy.delete(self.data,i,0)
            self._shape = (self._shape[0]-1,self.shape[1])
    

    也许我应该将这些函数提交到 Scipy 存储库。

    【讨论】:

      【解决方案3】:

      对于稀疏 csr 矩阵 (X) 和要删除的索引列表 (index_to_drop):

      to_keep = list(set(xrange(X.shape[1]))-set(index_to_drop))    
      new_X = X[:,to_keep]
      

      将 lil_matrices 转换为 csr_matrices 很容易。检查lil_matrix documentation中的tocsr()

      但是请注意,使用 tolil() 从 csr 到 lil 矩阵是昂贵的。因此,当您不需要将矩阵设为 lil 格式时,此选择是不错的选择。

      【讨论】:

        【解决方案4】:

        我是 python 新手,所以我的答案可能是错误的,但我想知道为什么下面这样的东西不会有效?

        假设您的 lil_matrix 称为 mat 并且您要删除第 i 列:

        mat=hstack( [ mat[:,0:i] , mat[:,i+1:] ] )
        

        现在矩阵将在此之后变成 coo_matrix,但您可以将其转回 lil_matrix。

        好的,我知道这将必须在 hstack 中创建两个矩阵,然后再分配给 mat 变量,所以它就像同时拥有原始矩阵加上一个矩阵,但我猜如果稀疏足够大,那么我认为不应该有任何内存问题(因为内存(和时间)是使用稀疏矩阵的全部原因)。

        【讨论】:

        • 这看起来像是一个问题而不是一个答案。
        【解决方案5】:
        
        def removecols(W, col_list):
                if min(col_list) = W.shape[1]:
                        raise IndexError('column index out of bounds')
                rows = W.rows
                data = W.data
                for i in xrange(M.shape[0]):
                    for j in col_list:
                        pos = bisect_left(rows[i], j)
                        if pos == len(rows[i]):
                                continue
                        elif rows[i][pos] == j:
                                rows[i].pop(pos)
                                data[i].pop(pos)
                                if pos == len(rows[i]):
                                        continue
                        for pos2 in xrange(pos,len(rows[i])):
                                rows[i][pos2] -= 1
                W._shape = (W._shape[0], W._shape[1]-len(col_list))
                return W
        
        

        只需重写您的代码以使用 col_list 作为输入 - 也许这会对某人有所帮助。

        【讨论】:

        • 我很高兴有人尝试改进我的第一次尝试。但是,if min(col_list) = W.shape[1]: 这行在很多方面对我来说没有意义。首先,在 Python 的 if 参数中使用赋值是无效的语法。其次,你为什么要检查 col_list 的最小值和形状?我在想也许你打算做if max(col_list) &gt;= W.shape[1]:?当然,这意味着您也不能使用负索引,并且没有任何检查低于 0 的索引以及如何处理它们。
        【解决方案6】:

        通过查看每个稀疏矩阵的注释,特别是在我们的例子中是 csc 矩阵,它具有文档[1]中列出的以下优点

        • 高效算术运算CSC + CSC、CSC * CSC等
        • 高效的列切片
        • 快速矩阵向量积(CSR、BSR 可能更快)

        如果您有要删除的列索引,只需使用切片即可。 删除行使用 csr 矩阵,因为它在行切片中很有效

        【讨论】:

          猜你喜欢
          • 2010-10-18
          • 2012-05-26
          • 2021-11-18
          • 2020-12-07
          • 2018-08-12
          • 2019-05-26
          • 1970-01-01
          • 1970-01-01
          • 2016-12-21
          相关资源
          最近更新 更多