如何高效地从稀疏矩阵中移除一列?

18 投票
6 回答
17089 浏览
提问于 2025-04-15 19:56

如果我在使用sparse.lil_matrix格式,怎么才能简单又高效地删除矩阵中的一列呢?

6 个回答

8

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

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

把lil矩阵转换成csr矩阵是很简单的。你可以查看tocsr(),了解更多关于lil_matrix的文档

不过要注意,从csr矩阵转换回lil矩阵(使用tolil())是比较耗费资源的。所以,如果你不需要把矩阵放在lil格式,这种选择是不错的。

12

这方法简单又快。你可能甚至不需要把数据转换成csr格式,但我可以肯定的是,它在csr稀疏矩阵上是有效的,转换格式应该不会有问题。

from scipy import sparse

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

我一直想要这个功能,实际上目前还没有很好的内置方法来实现。这里有一个解决办法。我选择创建一个名为 lil_matrix 的子类,并添加一个叫做 remove_col 的函数。如果你愿意,也可以直接在你的 lib/site-packages/scipy/sparse/lil.py 文件中给 lil_matrix 类添加 removecol 函数。以下是代码:

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 的代码库里。

撰写回答