如果我使用 sparse.lil_matrix 格式,如何轻松有效地从矩阵中删除一列?
6 回答
更简单,更快。您甚至可能不需要转换为 csr,但我只是确定它可以与 csr 稀疏矩阵一起使用,并且之间的转换应该不是问题。
from scipy import sparse
x_new = sparse.lil_matrix(sparse.csr_matrix(x)[:,col_list])
我自己一直想要这个,事实上还没有一个很好的内置方法来做到这一点。这是一种方法。我选择创建一个 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 存储库。
对于稀疏 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 文档中的 tocsr()
但是请注意,使用 tolil() 从 csr 到 lil 矩阵是昂贵的。因此,当您不需要将矩阵设为 lil 格式时,此选择是不错的选择。
我是 python 新手,所以我的回答可能是错误的,但我想知道为什么下面这样的东西不会有效?
假设您的 lil_matrix 称为 mat 并且您要删除第 i 列:
mat=hstack( [ mat[:,0:i] , mat[:,i+1:] ] )
现在矩阵将在此之后变为 coo_matrix,但您可以将其转回 lil_matrix。
好的,我知道这将不得不在 hstack 中创建两个矩阵,然后再分配给 mat 变量,所以它就像同时拥有原始矩阵加上一个矩阵一样,但我想如果稀疏性足够大那么我认为不应该有任何内存问题(因为内存(和时间)是使用稀疏矩阵的全部原因)。
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 作为输入 - 也许这对某人有帮助。
通过查看每个稀疏矩阵的注释,特别是在我们的例子中是 csc 矩阵,它具有文档[1]中列出的以下优点
- 高效算术运算 CSC + CSC、CSC * CSC 等
- 高效的列切片
- 快速矩阵向量积(CSR、BSR 可能更快)
如果您有要删除的列索引,只需使用切片。对于删除行使用 csr 矩阵,因为它在行切片中很有效