[英]How to efficiently remove columns from a sparse matrix that only contain zeros?
[英]How can I remove a column from a sparse matrix efficiently?
如果我使用的是sparse.lil_matrix格式,如何輕松有效地從矩陣中刪除列?
更簡單,更快捷。 您可能甚至不需要轉換為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]中列出的以下優點
如果您要刪除列索引,只需使用切片。 對於刪除行,請使用csr矩陣,因為它在行切片中很有效
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.