CSC mantiene un elenco degli indici di riga di tutte le voci diverse da zero, il formato CSR mantiene un elenco degli indici delle colonne di tutte le voci diverse da zero. Penso che si possa approfittare di questo per scambiare le cose intorno come segue, e penso che non ci dovrebbero essere effetti collaterali ad esso:
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)
Si potrebbe ora fare qualcosa di simile:
>>> 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.]])
Ho usato una matrice LIL per mostrare come è possibile conservare il tipo di output. Nella tua applicazione probabilmente vuoi già essere in formato CSC o CSR e selezionare se scambiare prima le righe o le colonne in base ad esso, per ridurre al minimo le conversioni.
Ho bisogno di questo per una particolare implementazione. Tuttavia, come mi ha fatto notare un collega, in generale, non si farebbero permutazioni su una matrice sparsa. Una matrice sparsa 'A' viene generalmente utilizzata come una mappa lineare' y = Ax ', ad es. in solutori iterativi. Quindi questo scambio si realizza meglio scrivendo un wrapper attorno a 'A', scambiando le voci del vettore di input x (questo è lo scambio di colonne in' A') o le voci di 'y' (questo è lo scambio di righe). – Jan