我有大而稀疏的数组,我想通过交换行来重新排列它们。在scipy.sparse
中执行此操作的好方法是什么?
一些问题
我不认为排列矩阵非常适合这项任务,因为他们喜欢随机改变稀疏结构。即使只需要少量交换,操纵也会“倍增”所有列或行。
scipy.sparse
中此任务的最佳稀疏矩阵表示是什么?
非常欢迎有关实施的建议。
我也用Matlab标记了这个,因为这个问题可能会找到一个不一定是scipy
特定的答案。
答案 0 :(得分:4)
CSC格式保留所有非零条目的行索引列表,CSR格式保留所有非零条目的列索引列表。我认为你可以利用这个来交换周围的东西如下,我认为不应该有任何副作用:
def swap_rows(mat, a, b) :
mat_csc = scipy.sparse.csc_matrix(mat)
a_idx = np.where(mat_csc.indices == a)
b_idx = np.where(mat_csc.indices == b)
mat_csc.indices[a_idx] = b
mat_csc.indices[b_idx] = a
return mat_csc.asformat(mat.format)
def swap_cols(mat, a, b) :
mat_csr = scipy.sparse.csr_matrix(mat)
a_idx = np.where(mat_csr.indices == a)
b_idx = np.where(mat_csr.indices == b)
mat_csr.indices[a_idx] = b
mat_csr.indices[b_idx] = a
return mat_csr.asformat(mat.format)
你现在可以这样做:
>>> mat = np.zeros((5,5))
>>> mat[[1, 2, 3, 3], [0, 2, 2, 4]] = 1
>>> mat = scipy.sparse.lil_matrix(mat)
>>> mat.todense()
matrix([[ 0., 0., 0., 0., 0.],
[ 1., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 0.],
[ 0., 0., 1., 0., 1.],
[ 0., 0., 0., 0., 0.]])
>>> swap_rows(mat, 1, 3)
<5x5 sparse matrix of type '<type 'numpy.float64'>'
with 4 stored elements in LInked List format>
>>> swap_rows(mat, 1, 3).todense()
matrix([[ 0., 0., 0., 0., 0.],
[ 0., 0., 1., 0., 1.],
[ 0., 0., 1., 0., 0.],
[ 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]])
>>> swap_cols(mat, 0, 4)
<5x5 sparse matrix of type '<type 'numpy.float64'>'
with 4 stored elements in LInked List format>
>>> swap_cols(mat, 0, 4).todense()
matrix([[ 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1.],
[ 0., 0., 1., 0., 0.],
[ 1., 0., 1., 0., 0.],
[ 0., 0., 0., 0., 0.]])
我使用了LIL矩阵来展示如何保留输出的类型。在您的应用程序中,您可能希望已经采用CSC或CSR格式,并根据它选择是先交换行还是列,以最大限度地减少转换。
答案 1 :(得分:0)
在Matlab中,您可以按照自己喜欢的方式索引列和行:
Matrix = speye(10);
mycolumnorder = [1 2 3 4 5 6 10 9 8 7];
myroworder = [4 3 2 1 5 6 7 8 9 10];
Myorderedmatrix = Matrix(myroworder,mycolumnorder);
我认为这可以保留稀疏性......虽然不知道scipy ......
答案 2 :(得分:0)
我发现使用矩阵运算是最有效的。这是一个将行和/或列排列到指定顺序的函数。如果需要,可以对其进行修改以交换两个特定的行/列。
from scipy import sparse
def permute_sparse_matrix(M, row_order=None, col_order=None):
"""
Reorders the rows and/or columns in a scipy sparse matrix to the specified order.
"""
if row_order is None and col_order is None:
return M
new_M = M
if row_order is not None:
I = sparse.eye(M.shape[0]).tocoo()
I.row = I.row[row_order]
new_M = I.dot(new_M)
if col_order is not None:
I = sparse.eye(M.shape[1]).tocoo()
I.col = I.col[col_order]
new_M = new_M.dot(I)
return new_M