我有一个稀疏矩阵的行信息的Python列表。每行表示为(列,值)元组的列表。叫它alist
:
alist = [[(1,10), (3,-3)],
[(2,12)]]
如何从列表列表中有效地构造一个scipy稀疏矩阵,得到如下矩阵:
0 10 0 -3
0 0 12 0
显而易见的方法是制作一个scipy.sparse.lil_matrix
,它内部有这个“列表列表”结构。但是从scipy.sparse.lil_matrix — SciPy v0.19.0 Reference Guide我看到了构建它们的三种方法:
因此,获取新数据的唯一方法是使用其他稀疏矩阵表示来解决此问题,或者从密集数组开始,这两者都没有解决初始问题,并且这两者似乎都是效率低于表示的lil_matrix
本身就是这个数据。
我想我可以制作一个空的,并使用循环来添加值,但我肯定错过了一些东西。
在稀疏矩阵方面,scipy文档非常令人沮丧。
您的数据布局是不寻常的。这是我第一次尝试使用它。
In [565]: M = sparse.lil_matrix((2,4), dtype=int)
In [566]: M
Out[566]:
<2x4 sparse matrix of type '<class 'numpy.int32'>'
with 0 stored elements in LInked List format>
In [567]: for i,row in enumerate(alist):
...: for col in row:
...: M[i, col[0]] = col[1]
...:
In [568]: M
Out[568]:
<2x4 sparse matrix of type '<class 'numpy.int32'>'
with 3 stored elements in LInked List format>
In [569]: M.A
Out[569]:
array([[ 0, 10, 0, -3],
[ 0, 0, 12, 0]])
是的,它是迭代的;和lil
是这个目的的最佳格式。
或使用常见的coo
输入风格:
In [580]: data,col,row = [],[],[]
In [581]: for i, rr in enumerate(alist):
...: for cc in rr:
...: row.append(i)
...: col.append(cc[0])
...: data.append(cc[1])
...:
In [582]: data,col,row
Out[582]: ([10, -3, 12], [1, 3, 2], [0, 0, 1])
In [583]: M1=sparse.coo_matrix((data,(row,col)),shape=(2,4))
In [584]: M1
Out[584]:
<2x4 sparse matrix of type '<class 'numpy.int32'>'
with 3 stored elements in COOrdinate format>
In [585]: M1.A
Out[585]:
array([[ 0, 10, 0, -3],
[ 0, 0, 12, 0]])
另一种选择是创建空白的lil
矩阵,并直接填写其属性:
换句话说,从:
In [591]: m.data
Out[591]: array([[], []], dtype=object)
In [592]: m.rows
Out[592]: array([[], []], dtype=object)
并将其更改为:
In [587]: M.data
Out[587]: array([[10, -3], [12]], dtype=object)
In [588]: M.rows
Out[588]: array([[1, 3], [2]], dtype=object)
它仍然需要你的alist
结构的2级迭代。
In [593]: for i, rr in enumerate(alist):
...: for cc in rr:
...: m.rows[i].append(cc[0])
...: m.data[i].append(cc[1])
In [594]: m
Out[594]:
<2x4 sparse matrix of type '<class 'numpy.int32'>'
with 3 stored elements in LInked List format>
In [595]: m.A
Out[595]:
array([[ 0, 10, 0, -3],
[ 0, 0, 12, 0]])
在另一个评论中你提到了理解csr
indptr
的困难。最简单的方法是转换这些格式:
In [597]: Mr=M.tocsr()
In [598]: Mr.indptr
Out[598]: array([0, 2, 3], dtype=int32)
In [599]: Mr.data
Out[599]: array([10, -3, 12])
In [600]: Mr.indices
Out[600]: array([1, 3, 2], dtype=int32)
如果在创建稀疏矩阵之前有整个alist
,则不需要使用lil_matrix
,因为它已经过优化,可以逐步更新稀疏矩阵。
如果你想在之后用矩阵进行任何算术运算,qazxsw poi可能是你最好的选择。您可以使用csr_matrix
格式直接构造qazxsw poi,如下所示:
csr_matrix
如果效率是一个真正的问题,您可以直接创建(data, (row, column))
内部格式(使用indptr):
In [40]: alist = [[(1,10), (3,-3)],
...: [(2,12)]]
In [41]: i, j, data = zip(*((i, t[0], t[1]) for i, row in enumerate(alist) for t in row))
In [42]: (i, j, data)
Out[42]: ((0, 0, 1), (1, 3, 2), (10, -3, 12))
In [43]: csr_matrix((data, (i, j)), shape=(2, 4)).todense()
Out[43]:
matrix([[ 0, 10, 0, -3],
[ 0, 0, 12, 0]], dtype=int64)
如果你之后转换为熊猫,qazxsw poi是要走的路,因为大熊猫无论如何都要转换为qazxsw poi:
csr_matrix
您可以从(列,值)元组In [57]: indptr = np.cumsum([0] + [len(row) for row in alist])
In [58]: j, data = zip(*(t for row in alist for t in row))
In [59]: csr_matrix((data, j, indptr), shape=(2, 4)).todense()
Out[59]:
matrix([[ 0, 10, 0, -3],
[ 0, 0, 12, 0]])
列表中创建位置和值的coo_matrix
,然后使用coo_matrix
构造稀疏矩阵
In [41]: i, j, data = zip(*((i, t[0], t[1]) for i, row in enumerate(alist) for t in row))
In [43]: coo_matrix((data, (i, j)), shape=(2, 4))
只想用dict
发布另一个答案,它是一种构造稀疏矩阵的快速格式。
alist