通常,要使用Scipy矩阵,请使用内置方法.但是有时您需要读取矩阵数据以将其分配给非稀疏数据类型.为了演示,我创建了一个随机的LIL稀疏矩阵,并使用不同的方法将其转换为Numpy数组(纯python数据类型会更好!).
from __future__ import print_function
from scipy.sparse import rand, csr_matrix, lil_matrix
import numpy as np
dim = 1000
lil = rand(dim, dim, density=0.01, format='lil', dtype=np.float32, random_state=0)
print('number of nonzero elements:', lil.nnz)
arr = np.zeros(shape=(dim,dim), dtype=float)
非零元素数:10000
通过索引阅读
%%timeit -n3
for i in xrange(dim):
for j in xrange(dim):
arr[i,j] = lil[i,j]
3个循环,每个循环最好3:6.42 s
使用nonzero()方法
%%timeit -n3
nnz = lil.nonzero() # indices of nonzero values
for i, j in zip(nnz[0], nnz[1]):
arr[i,j] = lil[i,j]
3个循环,最佳3:每个循环75.8毫秒
使用内置方法直接转换为数组
这不是读取矩阵数据的通用解决方案,因此不算作解决方案.
%timeit -n3 arr = lil.toarray()
3个循环,每个循环最好3:7.85毫秒
用这些方法读取Scipy稀疏矩阵根本没有效率.有没有更快的方法来读取这些矩阵?
解决方法:
一个类似的问题,只是处理设置稀疏值,而不是仅仅读取它们:
Efficient incremental sparse matrix in python / scipy / numpy
有关使用基础表示访问值的更多信息
Efficiently select random non-zero column from each row of sparse matrix in scipy
也
why is row indexing of scipy csr matrices slower compared to numpy arrays
Why are lil_matrix and dok_matrix so slow compared to common dict of dicts?
看一下M.nonzero的功能:
A = self.tocoo()
nz_mask = A.data != 0
return (A.row[nz_mask],A.col[nz_mask])
在过滤掉.data属性中的任何“杂散” 0之后,它将矩阵转换为coo格式并返回.row和.col属性.
因此,您可以跳过中间人并直接使用这些属性:
A = lil.tocoo()
for i,j,d in zip(A.row, A.col, A.data):
a[i,j] = d
这几乎与toarray一样好:
In [595]: %%timeit
.....: aa = M.tocoo()
.....: for i,j,d in zip(aa.row,aa.col,aa.data):
.....: A[i,j]=d
.....:
100 loops, best of 3: 14.3 ms per loop
In [596]: timeit arr=M.toarray()
100 loops, best of 3: 12.3 ms per loop
但是,如果您的目标确实是一个数组,则不需要迭代
In [603]: %%timeit
.....: A=np.empty(M.shape,M.dtype)
.....: aa=M.tocoo()
.....: A[aa.row,aa.col]=aa.data
.....:
100 loops, best of 3: 8.22 ms per loop
我对@Thoran的2种方法的评价是:
100 loops, best of 3: 5.81 ms per loop
100 loops, best of 3: 17.9 ms per loop
时光倒流.