class SparseRowIndexer:
def __init__(self, csr_matrix):
data = []
indices = []
indptr = []
# Iterating over the rows this way is significantly more efficient
# than csr_matrix[row_index,:] and csr_matrix.getrow(row_index)
for row_start, row_end in zip(csr_matrix.indptr[:-1], csr_matrix.indptr[1:]):
data.append(csr_matrix.data[row_start:row_end])
indices.append(csr_matrix.indices[row_start:row_end])
indptr.append(row_end-row_start) # nnz of the row
self.data = np.array(data)
self.indices = np.array(indices)
self.indptr = np.array(indptr)
self.n_columns = csr_matrix.shape[1]
def __getitem__(self, row_selector):
data = np.concatenate(self.data[row_selector])
indices = np.concatenate(self.indices[row_selector])
indptr = np.append(0, np.cumsum(self.indptr[row_selector]))
shape = [indptr.shape[0]-1, self.n_columns]
return sparse.csr_matrix((data, indices, indptr), shape=shape)
2条答案
按热度按时间hpcdzsge1#
要获得一个稀疏矩阵作为输出,最快的行切片方法是使用
csr
类型,而对于列切片则是csc
类型,如下所述。在这两种情况下,您只需执行当前正在执行的操作:如果您想要将
ndarray
作为输出,直接在ndarray
对象中执行切片可能会更快,您可以使用.A
属性或.toarray()
方法从稀疏矩阵中获取该对象:或:
正如下面的注解中所提到的,如果数组足够大,将稀疏数组转换为密集数组可能会导致内存错误。
vhipe2zx2#
我发现,通过滚动自己的行索引器,可以使
scipy.sparse.csr_matrix
所宣传的快速行索引更快。也就是说,通过将每行的非零值存储在单独的数组中,可以利用numpy数组的快速索引,(每行的长度不同),并将所有这些行数组放入对象类型数组中(允许每行具有不同的大小)。列索引以相同的方式存储。该方法与标准CSR数据结构略有不同,后者将所有非零值存储在单个数组中,需要查找以查看每行的起始位置和结束位置。这些查找可能会降低随机访问的速度,但对于检索连续行应该是有效的。
分析结果
我的矩阵
mat
是一个1,900,000x1,250,000csr_matrix
,其中有400,000,000个非零元素。ilocs
是一个200,000个随机行索引的数组。比较对象:
与布尔掩码相比,SparseRowIndexer在使用花哨的索引时似乎速度更快。