8

我有大而稀疏的数组,我想通过交换行和列来重新排列它们。什么是这样做的好方法scipy.sparse

一些问题

  • 我不认为置换矩阵非常适合这项任务,因为它们喜欢随机改变稀疏结构。并且操作将始终“乘以”所有列或行,即使只需要几次交换。

  • scipy.sparse这项任务的最佳稀疏矩阵表示是什么?

  • 非常欢迎提出实施建议。

我也用 Matlab 标记了这个,因为这个问题可能会找到一个不一定scipy具体的答案。

4

3 回答 3

5

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 格式,并根据它选择是否首先交换行或列,以最大限度地减少转换。

于 2013-03-01T16:50:17.593 回答
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...

于 2013-03-01T15:55:21.507 回答
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
于 2020-07-23T14:53:08.823 回答