如何有效地从稀疏矩阵中删除列?

时间:2010-03-03 03:25:01

标签: python matrix numpy scipy algebra

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

6 个答案:

答案 0 :(得分:10)

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

from scipy import sparse

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

答案 1 :(得分:7)

我一直想要这个,事实上还没有一个很好的内置方法来做到这一点。这是一种方法。我选择创建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存储库。

答案 2 :(得分:4)

对于稀疏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格式使用矩阵时,这种选择很好。

答案 3 :(得分:2)

我是python的新手,所以我的回答可能是错的,但我想知道为什么类似下面的内容效率不高?

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

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

现在矩阵将变为coo_matrix,但你可以将它变回lil_matrix。

好的,我知道这必须在hstack中创建两个矩阵,然后才能对mat变量进行赋值,这样就可以让原始矩阵再加上一个,但我猜是否稀疏我认为应该没有任何内存问题(因为内存(和时间)是使用稀疏矩阵的全部原因)。

答案 4 :(得分:0)


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作为输入 - 也许这对某些人有用。

答案 5 :(得分:0)

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

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

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