我试图在稀疏矩阵中按行找到非零项的索引:scipy.sparse.csc_matrix。到目前为止,我正在遍历矩阵中的每一行,并使用
numpy.nonzero()
到每一行以获取非零列索引。但是这种方法需要花费一个多小时才能找到每行的非零列条目。有快速的方法吗?谢谢!
答案 0 :(得分:7)
使用.nonzero()
方法。
indices = sp_matrix.nonzero()
如果您希望索引为(row, column)
元组,则可以使用zip
。
indices = zip(*sp_matrix.nonzero())
答案 1 :(得分:3)
如果使用coo_matrix,这将非常简单,并且coo / csr / csc之间的转换速度非常快。分别获取所有行和列索引可以按如下方式完成:
sp_matrix = sp_matrix.tocoo()
row_ind = sp_matrix.row
col_ind = sp_matrix.col
但是你也可以同时为这些稀疏矩阵类型获得两组索引,这可能是最简单的:
rows, cols = X.nonzero()
如果需要在特定行中查找值,csc和csr矩阵将返回按行排序的非零条目,现在,铜似乎返回按列排序的索引。
In [1]: X = coo_matrix(([1, 2, 3, 4, 5, 6], ([0, 2, 2, 0, 1, 2], [0, 0, 1, 2, 2, 2])))
In [2]: X.todense()
Out[2]:
matrix([[1, 0, 4],
[0, 0, 5],
[2, 3, 6]])
In [3]: X.nonzero()
Out[3]:
(array([0, 2, 2, 0, 1, 2], dtype=int32),
array([0, 0, 1, 2, 2, 2], dtype=int32))
In [4]: X.tocsr().nonzero()
Out[4]:
(array([0, 0, 1, 2, 2, 2], dtype=int32),
array([0, 2, 2, 0, 1, 2], dtype=int32))
答案 2 :(得分:3)
CSR矩阵相对简单,因此您可以随时执行:
>>> a = sps.rand(5, 5, .2, format='csc')
>>> a.A
array([[ 0. , 0. , 0.68642384, 0. , 0. ],
[ 0.46120599, 0. , 0.83253467, 0. , 0. ],
[ 0. , 0. , 0. , 0. , 0.07074811],
[ 0. , 0. , 0. , 0. , 0. ],
[ 0. , 0.21190832, 0. , 0. , 0. ]])
>>> b = a.tocsr()
>>> np.split(b.indices, b.indptr[1:-1])
[array([2]), array([0, 2]), array([4]), array([], dtype=float64), array([1])]
答案 3 :(得分:2)
我假设您的矩阵不对称,否则在一行中查找所有非零条目与在一列中查找所有这些条目相同。您正在使用的矩阵的维度是多少,平均每列有多少非零条目?
如果您的矩阵有m
行和n
列,并且您以CSC格式存储它,则可以在O(d)时间内返回列中的所有非零条目,其中d列中的非零条目数,但无法以小于O(n)的形式返回行中的所有非零条目;你必须遍历整行。
我会以CSR格式制作矩阵的副本并从中获取行而不是原始CSC矩阵。当然,你当然会使用两倍的内存,所以希望它不会那么大,以免排除额外的开销。这看起来像这样:
A = csc_matrix((m, n), dtype = float)
<fill A>
B = csr_matrix(A)
for i in range(m):
_, cols = B[i, :].nonzero()
for j in cols:
<do some stuff>
我不使用COO格式,因为在最坏的情况下获取给定行中的所有非零条目可能需要O(nnz)时间,其中nnz
是整个矩阵的非零项数。
如果您发现自己不得不经常使用稀疏矩阵,您可能需要查看this book。它描述了许多常见的和不常见的稀疏矩阵格式,并说明了它们之间的一些差异。没有一种最好的存储格式;他们都有自己的权衡。
答案 4 :(得分:0)
您希望这些指数采用何种形式?例如
x=sparse.csr_matrix([[1,2,0,3,0,0],[0,0,0,1,0,0]])
In [15]: for r in x:
....: print r.nonzero()
(array([0]), array([0]))
(array([0, 0]), array([0, 2]))
(array([0, 0, 0]), array([0, 1, 2]))
In [30]: [r.nonzero()[1] for r in x] # or as list
Out[30]: [array([0]), array([0, 2]), array([0, 1, 2])]
In [16]: x.nonzero()
Out[16]: (array([0, 1, 1, 2, 2, 2]), array([0, 0, 2, 0, 1, 2]))
整个矩阵上的 nonzero
具有相同的数字,但它们不会分成子列表。但tolil
格式与列表列表具有相同的信息。
In [18]: xl=x.tolil()
In [19]: xl.rows
Out[19]: array([[0], [0, 2], [0, 1, 2]], dtype=object)
In [23]: xc=x.tocoo()
In [24]: xc.row
Out[24]: array([0, 1, 2, 2, 1, 2])
In [25]: xc.col
Out[25]: array([0, 0, 0, 1, 2, 2])
在coo
格式中,存在相同的索引,但顺序不同。但首先将其转换为csr
,订单为
In [29]: x.tocsr().tocoo().col
Out[29]: array([0, 0, 2, 0, 1, 2])