我有大而稀疏的数组,我想通过交换行和列来重新排列它们。什么是这样做的好方法scipy.sparse
?
一些问题
我不认为置换矩阵非常适合这项任务,因为它们喜欢随机改变稀疏结构。并且操作将始终“乘以”所有列或行,即使只需要几次交换。
scipy.sparse
这项任务的最佳稀疏矩阵表示是什么?非常欢迎提出实施建议。
我也用 Matlab 标记了这个,因为这个问题可能会找到一个不一定scipy
具体的答案。
我有大而稀疏的数组,我想通过交换行和列来重新排列它们。什么是这样做的好方法scipy.sparse
?
一些问题
我不认为置换矩阵非常适合这项任务,因为它们喜欢随机改变稀疏结构。并且操作将始终“乘以”所有列或行,即使只需要几次交换。
scipy.sparse
这项任务的最佳稀疏矩阵表示是什么?
非常欢迎提出实施建议。
我也用 Matlab 标记了这个,因为这个问题可能会找到一个不一定scipy
具体的答案。
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 格式,并根据它选择是否首先交换行或列,以最大限度地减少转换。
在 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...
我发现使用矩阵运算是最有效的。这是一个将行和/或列排列为指定顺序的函数。如果您愿意,可以修改它以交换两个特定的行/列。
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